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

それはいいですね。特別なフォームをラップする関数を書いて、その関数を渡すことができることはわかっています。

しかし、Lisp にこの制限がある理由と、これを許可するとどのような悪影響があるかを知りたいです。それを可能にする主要な方言はありますか?

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は実際には値としてではなく、フォームとして#fとを受け取ります。(modulo (+ a b) n)そしてこれは重要です!(modulo x n)が0の場合は失敗しnます。そのため、0でないことがわかるまで未評価のままになりnます。

特殊なフォームをファーストクラスのオブジェクトとして渡すことができる場合の問題は、高階関数が予測可能なセマンティクスを使用してそれらのオブジェクトを呼び出すことができないことです。それは関数オブジェクトであるため、値を渡すのでしょうか、それとも特殊なフォームであるのか、フォームを渡すように?これは大きな混乱になります。

modaddはい、をカプセル化する私のようなラッパー関数を書くことができますififただし、ブランチの1つだけを評価する動作を維持しながら、関数として再実装する方法はありません。

于 2012-07-04T17:14:40.977 に答える
4

評価がより複雑になり、コンパイルが難しくなります。

フォームがある場合は、(a b c)実行時に の値を解決し、aそれを何らかの方法でフォームbおよびに適用する必要がありcます。

いくつかの限られた数の特別なフォームと厳密な評価の単純なモデルは、その後なくなりました。

参照: FEXPR

于 2012-07-04T18:42:09.440 に答える