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

use*_*ond 9 scheme programming-languages functional-programming racket

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

关于康德的事情

  • 它允许多个测试和替代表达式
  • 它具有预先指定的评估顺序.例如,第一个条件将始终评估它是否正确

我无法区分的一件事是cond与函数有什么不同!

soe*_*ard 10

函数调用(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`.
Run Code Online (Sandbox Code Playgroud)

请注意,在激活函数体之前,将评估所有表达式e0,, e1e2.

这意味着函数调用 (foo #t 2 (/ 3 0))会在(/ 3 0)评估时导致错误- 在将控制权移交给正文之前foo.

现在考虑特殊形式if.在(if #t 2 (/ 3 0))表达式#t中进行求值,并且由于值为非假,所以计算第二个表达式2,结果值为2.这里(/ 3 0)永远不会计算.

如果相反if是一个函数,则表达式#t,2以及,(/ 3 0)被被激活体前评估.现在(/ 3 0)会产生错误 - 即使不需要表达式的值.

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

这里ifcond是形式的例子,不评估所有的子表达式-因此他们,他们需要特殊形式.


ben*_*ers 5

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

((> number 1)         ;;3rd
 (+ number (triangle-using-cond (1- number))))
Run Code Online (Sandbox Code Playgroud)

会导致:

  • 无限循环因为triangle-using-cond会通过尾调用递归调用自身 (triangle-using-cond (1- number)).

  • 或者,最后一个表达式将尝试应用该值#f#t作为函数(在类型2 Lisp中,例如ANSI Common Lisp是可能的,但在类型1 Lisp中不可能,例如Racket或Scheme)并产生错误.

什么使得cond一个特殊的形式是它的参数被懒惰地评估,而Scheme或Common Lisp中的函数急切地评估它们的参数.