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

时间:2015-11-01 18:32:56

标签: functional-programming scheme programming-languages 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))))))

我对Cond了解的事情

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

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

3 个答案:

答案 0 :(得分: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`.

请注意,所有表达式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是表单的示例,不会评估所有子表达式 - 因此它们需要是特殊表单。

答案 1 :(得分:5)

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

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

会导致:

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

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

使cond成为一种特殊形式的原因是它的参数被懒惰地评估,而Scheme或Common Lisp中的函数则急切地评估它们的参数。

答案 2 :(得分:4)

如前所述,在计算应用 f 的结果之前,将评估对某个函数 f 的调用的所有参数。是否意味着condif或两者都应该是特殊形式?

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

那么if会特别吗?

它真的不需要......

如果基本问题&#34; if可用较小的特殊表格形式表达?&#34; ,那么答案是是< / em>:只需实施if in terms of functions

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

每当您可以返回布尔值时,您将返回上述函数之一。 例如,您可以决定将#t#f绑定到这些函数。 注意他们如何调用两个输入参数之一。

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

...但为什么要在lambda演算中编码?

有条件地评估代码实际上是计算的基本操作。试图找到一个最小的特殊形式,你无法直接表达,从程序员的角度来看,较差的编程语言,然而&#34; clean&#34;核心语言是。

从某个角度来看if表单(或cond必要因为没有它们就很难表达条件执行以编译器/解释器可以有效处理的方式执行。

This document引用的

uselpa讨论使用闭包来实现if,并得出结论:

  

然而,语法上的不便甚至会如此巨大   Scheme定义是否作为特殊形式。