2016-10-17 64 views
0

我正在慢慢学习Scheme并通过阅读在线教程Write Yourself a Scheme in 48 Hours来修改Haskell。我刚刚得到了this部分,它向我们介绍了Scheme中的一些比较运算符。为什么字符串和数字有单独的比较函数/运算符?

("=", numBoolBinop (==)), 
("<", numBoolBinop (<)), 
(">", numBoolBinop (>)), 
("/=", numBoolBinop (/=)), 
(">=", numBoolBinop (>=)), 
("<=", numBoolBinop (<=)), 
("&&", boolBoolBinop (&&)), 
("||", boolBoolBinop (||)), 
("string=?", strBoolBinop (==)), 
("string<?", strBoolBinop (<)), 
("string>?", strBoolBinop (>)), 
("string<=?", strBoolBinop (<=)), 
("string>=?", strBoolBinop (>=)), 

我有几个新手问题。 1.为什么有不同类型的单独比较运算符,而不是一个通用运算符或一个有许多超载的运算符? 2.有可能有一个适用于所有类型的“通用”相等运算符,它将如何实现?如果不是所有类型,那么至少对于字符串和数字?

回答

0

计划有不相交的类型,并决定不进行通用比较。究其原因可能是

  1. 的标准,也没有任何方法覆盖
  2. 从历史上看,我们使用string-refvector-ref喜欢的东西,而不是一个普通的ref

所以这是很自然的,它没有通用的比较程序。唯一的例外是数字比较程序。

正如我上面提到的方案标准没有任何方法覆盖机制,但tt不可能做出通用程序。您只需要将它们构建在其他面向对象的库上,如Tiny CLOS。

如果你只需要他们的字符串和数字,你也可以做这样的事情:

(define (generic= n/s1 n/s2 . rest) 
    (cond ((for-all number? (cons* n/s1 n/s2 rest)) 
     (apply = n/s1 n/s2 rest)) 
     ((for-all string? (cons* n/s1 n/s2 rest)) 
     (apply string=? n/s1 n/s2 rest)) 
     (else (assertion-violation 'generic= "type not supported")))) 
1

要只回答第二个问题:不,它不是。首先,eq?和任何其他的相等谓词之间存在差异,并且eq?几乎不可避免地具有不可靠的数字行为。所以你至少需要eq?和一个“语义”等式谓词。但是这样的语义相等谓词不能存在,因为语言无法知道你想要的语义。例如,这应该返回什么?

(let ([c (cons #f #f)]) 
    (let ([a (cons c c)] 
     [b (cons (cons #f #f) (cons #f #f))]) 
    (general-semantic-equal? a b))) 

那么,它是否应该返回true或false取决于程序是否事项汽车和a CDR是eq?而那些b都没有。这个问题不是在不知道程序在做什么的情况下可以回答的问题:等式谓语是依赖于应用程序的,语言能够做的最好的是提供一个工具包,它允许你创建一个。

相关问题