为什么字符串和数字有单独的比较函数/运算符?

时间:2016-10-17 05:31:08

标签: generics polymorphism scheme operators lisp

我正在通过阅读在线教程Write Yourself a Scheme in 48 Hours慢慢学习Scheme并修改Haskell。我刚刚开始this部分,它向我们介绍了Scheme中的一些比较运算符。

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

我有几个新手问题。 1.为什么有不同类型的单独比较运算符,而不是一个通用运算符或一个具有多个重载的运算符? 2.是否可以拥有&#34;泛型&#34;适用于所有类型的平等运算符以及如何实现?如果不适用于所有类型,那么至少对于字符串和数字?

2 个答案:

答案 0 :(得分: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的{​​{1}} }} 不是。如果不知道程序在做什么就可以回答这个问题:等式谓词依赖于应用程序,语言可以做的最好的就是提供一个允许你构建一个的工具包。

答案 1 :(得分:0)

Scheme具有不相交的类型,并决定不进行通用比较。原因可能是

  1. 标准没有任何方法覆盖
  2. 从历史上看,我们使用string-refvector-ref类似的东西,而不是一个通用ref
  3. 所以它很自然,它没有通用的比较程序。唯一的例外是数字比较程序。

    正如我上面提到的,Scheme标准没有任何方法覆盖机制,但是不可能制作通用程序。您只需要在其他面向对象的库(例如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"))))