3
user=> (eval '(+ 1 2))
3
user=> (eval '('+ 1 2))
2
user=> (eval (list '+ '1 '2))
3
user=> (eval (list + '1 '2))
3

それは '+ が + と同じ場合があるということですか?

どのような状況を考慮する必要があるかを決定する規則はありますか?

4

1 に答える 1

5

(list '+ '1 '2)記号+と数字1とのリストを生成し2ます。それを評価すると、シンボルによって名前が付けられた関数が検索され、引数および+で呼び出されます。12

(list + '1 '2)は、記号+と数字1およびで名前が付けられた関数のリストを生成し2ます。それを評価すると、リストの残りの部分からの引数を使用して、すでに直接リストの要素である関数が呼び出されます。

ちなみに、数字を引用する必要はありません。彼らは自己評価しています。

編集

あなたが見出しで取り上げなかった興味深い事件は、その(eval '('+ 1 2))事件で何が起こったのかということですか? なぜこれは、引数とで3名前が付けられた関数を呼び出すことになる他のケースのように返されないのですか?+12

答えは、今回は記号+を 2 回引用したため、異なるということです。そのため、シンボルは名前が付けられた関数に解決されず、代わりにシンボル自体が関数として呼び出されます。

シンボルが関数として呼び出されたときの動作は何ですか? 最初の引数をマップとして扱い、そのマップ内のキーとして自分自身を検索します。しかし、数値1は明らかにマップではないため、通常nil、一致するキーが見つからなかったことを示すために返されます。

ただし、この場合、シンボルの呼び出しには2 番目の+引数があり、その 2 番目の引数は、一致するキーが見つからない場合に返されるデフォルト値として使用されます。そのため、フォームは を(eval '('+ 1 2))返します2

編集2

listでは、最後に質問に答えます。リストを引用すると、同じ引数で関数を呼び出すのとは異なる結果が生じるのはなぜですか。これは、引用符'が使用されているリストのすべての評価を停止するためですが、list関数はその引数を要素としてリストを生成する前に評価します。

これらの違いはすべて、さまざまなフォームを に直接送信する代わりに印刷すると、非常に明確になりますeval

user> '(+ 1 2)
(+ 1 2)
user> '('+ 1 2)
((quote +) 1 2)
user> (list '+ '1 '2)
(+ 1 2)
user> (list + '1 '2)
(#<core$_PLUS_ clojure.core$_PLUS_@165c64> 1 2)

最初と 3 番目のケースでは同じ結果が出力されることがわかります+。2 番目のケースで+は、代わりに 2 回引用され、最後のケースではまったく引用されていません。

編集3

物事をさらに明確にする最後の追加: 最初の要素がマクロまたは特別な演算子を指定しない限りeval、リスト自体を評価する前に、(評価された) 最初の引数をリストの残りを引数とする関数。

その最初の要素が'+orである場合(quote +)(これらは、同じものを引用符で囲まれた記号 で表す 2 つの異なる方法です+)、記号に評価され+、関数として呼び出されます。

最初の要素が の場合+、それは実際の加算関数 ( clojure.core$_PLUS_) に評価されます。すでにその関数である場合は、同じままです (基本的に、リストとシンボル以外のすべての型は自己評価型です)。どちらの場合も、evalその関数を呼び出します。

于 2013-10-01T10:25:18.990 に答える