为什么 cond 在 Scheme 中是一种特殊形式,而不是函数?

Why is cond a special form in Scheme, rather than a function?

(defun triangle-using-cond (number)
  (cond 
    ((<= number 0) 0) ; 1st
    ((= number 1) 1)  ; 2nd
    ((> number 1)     ; 3rd
      ;; 4th
      (+ number
         (triangle-using-cond (1- number))))))

我对Cond的了解

我无法区分的一件事是 cond 与函数的不同之处!

一个函数调用(e0 e1 e2)是这样计算的

1. e0 is evaluated, the result is (hopefully) a function f
2. e1 is evaluated, the result is a value v1
3. e2 is evaluated, the result is a value v2
4. The function body of `f` is evaluated in an environment in which
   the formal parameters are bound to the values `v1` and `v2`.

请注意,所有表达式 e0e1e2 在函数主体被激活之前计算。

这意味着像 (foo #t 2 (/ 3 0)) 这样的函数调用将在计算 (/ 3 0) 时导致错误 - 在控制权移交给 foo 的主体之前。

现在考虑特殊形式if。在 (if #t 2 (/ 3 0)) 中,表达式 #t 被求值,由于值非假,第二个表达式 2 被求值,结果值为 2。这里 (/ 3 0) 永远不会被求值。

相反,如果 if 是一个函数,那么表达式 #t2(/ 3 0) 在函数体被激活之前计算。现在 (/ 3 0) 将产生错误 - 即使不需要该表达式的值。

简而言之:在将控件传递给函数体之前,函数调用将始终评估所有参数。如果不对某些表达式求值,则需要特殊形式。

此处 ifcond 是形式的示例,它们不会计算所有子表达式 - 因此它们需要是特殊形式。

如果 cond 不是特殊形式,则表达式:

((> number 1)         ;;3rd
 (+ number (triangle-using-cond (1- number))))

会导致:

  • 一个无限循环,因为 triangle-using-cond 会通过尾部调用 (triangle-using-cond (1- number)).

  • 递归调用自身
  • 或者,最后一个表达式将尝试将值 #f#t 应用为函数(这在 type-2 Lisp 中是可能的,例如 ANSI Common Lisp , 但在 Racket 或 Scheme 等类型 1 Lisp 中是不可能的) 并产生错误。

cond 之所以成为一种特殊形式,是因为它的参数是惰性求值的,而 Scheme 或 Common Lisp 中的函数是急切求值的。

正如已经回答的那样,在计算应用 f 的结果之前,对调用某个函数 f 的所有参数进行求值。然而,这是否意味着 condif 或两者都应该是特殊形式?

嗯,首先,如果你有 if,你可以很容易地用嵌套测试模拟 cond。相反,if 只是 cond 的退化形式。所以你可以说其中之一有一个特殊的形式就足够了。我们选择 if 因为它更容易指定。

那么if应该是特别的吧?

其实不需要...

如果基础问题是"is if expressible in terms of a smaller set of special forms?",那么答案是:只需实施ifin terms of functions:

(define true-fn (lambda (then else) (then)))
(define false-fn (lambda (then else) (else)))

只要你可以 return 一个布尔值,你就 return 上面的函数之一。 例如,您可以决定将 #t#f 绑定到这些函数。 注意他们如何调用两个输入参数之一。

((pair? x) ;; returns either true-fn or false-fn 
  (lambda () (+ x 1))
  (lambda () x))

...但是为什么要用 lambda 演算编写代码?

有条件地评估代码确实是计算的基本操作。试图找到一种你无法表达的最小特殊形式,从程序员的角度来看,这会直接导致 较差 编程语言,但是 "clean" 核心语言是。

从某种角度if形式(或cond是必要的因为没有它们,就很难以 compiler/interpreter 可以有效处理的方式表达条件执行。

This document referenced by 讨论使用闭包实现 if,并得出结论:

However, the syntactic inconvenience would be so great that even Scheme defines if as a special form.