1

我发现在 Clojure 中,特殊形式不能作为参数传递或保存在变量中:

user=> (defn my-func 
         [op] 
         (op 1 2 3))
#'user/my-func
user=> (my-func +)
6
user=> (my-func if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5)
user=> (def my-if if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9)

在球拍/方案中:

> (define (my-func op)
    (op 1 2 3))
> (my-func +)
6
> (my-func if)
  if: bad syntax in: if
> (define my-if if)
  *if: bad syntax in: if

这很酷,我很好,我知道我可以编写一个函数来包装一个特殊的表单,然后传递那个函数。

但我想知道为什么 Lisps 有这个限制,以及允许这样做会产生什么负面影响。他们是否有任何允许这样做的主要方言?

4

2 回答 2

4

特殊形式不是函数:函数将值作为参数,而特殊形式采用形式。例如,看看你的例子if

(if 1 2 3)

好的,这很容易,因为 2 和 3 已经是值。但是这个呢?

(define (modadd a b n)
  (if (zero? n) #f (modulo (+ a b) n)))

在这种情况下,if实际是接收#fand(modulo (+ a b) n)作为形式,而不是值。这很重要!(modulo x n)如果为 0 将失败n:这就是为什么在我们知道它n不是 0 之前不对其进行评估的原因。

能够将特殊形式作为一等对象传递的问题在于,高阶函数不能使用可预测的语义调用这些对象:它是一个函数对象,以便您传递值,还是它是一个特殊形式,这样你就可以传递表格了吗?这将是一个巨大的混乱。

是的,您可以编写一个封装函数,例如 my modadd,它封装if. 但是,您无法仅将其重新实现if为一个函数,同时仍保留唯一评估一个分支的行为。

于 2012-07-04T17:14:40.977 回答
4

It makes evaluation more complicated and compilation hard.

If you have a form (a b c), then you need to resolve at runtime the value of a and then apply it somehow to the forms b and c.

The simpler model of a few limited number of special forms and otherwise strict evaluation is then gone.

See also: FEXPR

于 2012-07-04T18:42:09.440 回答