8

私は Clojure を学んでおり、Python の同様の機能との類似点を描くことによって、読者、引用、評価、ホモイコニシティを理解しようとしています。

Python では、評価を回避 (または延期) する 1 つの方法は、式を引用符で囲むことです。'3 + 4'. これは後で を使用して評価できますevaleval('3 + 4')お譲りし7ます。(Python 値のみを引用する必要がある場合はrepr、引用符を手動で追加する代わりに関数を使用できます。)

Lisp では、引用や評価にquoteorを使用します。お譲りします。'eval(eval '(+ 3 4))7

したがって、Python では「引用符で囲まれた」ものは文字列で表されますが、Lisp ではquote最初の項目を持つリストで表されます。

最後に、私の質問:引用されていない(eval 3)にもかかわらず、Clojure が許可するのはなぜですか? 3それは Lisp スタイル (可能な限りエラーの代わりに答えを出そうとする) の問題ですか、それとも他の理由があるのでしょうか? この動作は Lisp にとって不可欠ですか?

4

4 に答える 4

6

簡単に言うと、数字 (および記号、文字列など) はそれ自体に評価されます。引用符は、引用符に続くものを評価せずに渡すように Lisp (リーダー) に指示します。eval次に、あなたが書いたとおりにそのリストを取得しますが、引用符なしで、それを評価します ( の場合、(eval '(+ 3 4))は2 つの引数evalで関数呼び出し ( +) を評価します)。

その最後の式で何が起こるかは次のとおりです。

  1. Enter キーを押すと、式が評価されます。これには、通常の関数呼び出し ( eval) といくつかの引数が含まれています。
  2. 引数が評価されます。最初の引数には引用符が含まれており、引用符の後にあるもの (実際のリスト)を作成するようリーダーに指示します。(+ 3 4)
  3. これ以上引数はなく、実際の関数呼び出しが評価されます。これは、リストを引数としてeval関数を呼び出すことを意味します。 (+ 3 4)
  4. eval関数は同じ手順を繰り返して通常の関数と引数を見つけ、それ+を適用して結果を取得します。
于 2012-12-27T00:53:06.083 に答える
4

他の回答で仕組みが説明されていますが、哲学的なポイントは、lisp と python が「コード」を異なる方法で見ることにあると思います。Python では、コードを表す唯一の方法は文字列であるため、もちろん文字列以外を評価しようとすると失敗します。Lisp には、リスト、数値、記号など、コード用の豊富なデータ構造があります。したがって、式(+ 1 2)は記号と 2 つの数値を含むリストです。リストを評価するときは、まず各要素を評価する必要があります。

したがって、Lisp コードを実行する通常の過程で数値を評価する必要があるのはまったく自然なことです。そのために、数字は「自分自身に評価する」ように定義されています。つまり、評価後も前と同じ、つまり単なる数字です。この関数は、たとえば のような大きな式の 3 番目の要素をコンパイルするときに、コンパイラが適用するevalのと同じ規則をそのままの「コード スニペット」に適用します。数字の場合、それはそのままにしておくことを意味します。3(+ 5 3)

于 2012-12-27T01:58:13.630 に答える
3

何を3評価する必要がありますか?Lisp が数値をそれ自体に評価することは最も理にかなっています。コード内で数値を引用する必要がありますか? それはあまり便利ではなく、非常に問題があります。

それ以外の

(defun add-fourtytwo (n)
   (+ n 42))

私たちは書かなければならないでしょう

(defun add-fourtytwo (n)
   (+ n '42))

コード内のすべての数字を引用符で囲む必要があります。引用符が欠落していると、エラーが発生します。それは使いたいものではありません。

eval補足として、コードで使用したいときに何が起こるか想像してみてください。

(defun example ()
  (eval 3))

上は間違っているでしょう。数字を引用する必要があります。

 (defun example ()
   (eval '3))

上記は問題ありませんが、実行時にエラーが発生します。Lisp'3は数値 3 に評価します。しかし、eval数値を引用するとエラーになります。

したがって、次のように書く必要があります。

(defun example ()
   (eval ''3))

それはあまり役に立ちません...

Lisp の歴史において、数値は常に自己評価的でした。しかし、以前の Lisp 実装では、配列などの他のデータ オブジェクトは自己評価していませんでした。繰り返しますが、これはエラーの大きな原因であるため、Common Lisp のような Lisp の方言は、すべてのデータ型 (リストとシンボル以外) が自己評価型であると定義しています。

于 2012-12-27T01:30:48.313 に答える
2

この質問に答えるにはeval、Lisp での定義を調べる必要があります。たとえば、CLHSには定義があります。

構文: eval フォーム => 結果*

引数と値: form - フォーム。
results - フォームの評価によって得られた値。

どこformですか

  1. 評価されることを意図した任意のオブジェクト。
  2. シンボル、複合フォーム、または自己評価オブジェクト。
  3. (演算子の場合、<<operator>> form'') a compound form having that operator as its first element.「引用形式は定数形式です。」

あなたの場合、番号「3」はself-evaluating objectです。Self-evaluating objectですa form that is neither a symbol nor a cons is defined to be a self-evaluating object。clojure の場合、この定義で置き換えるだけでよいと思いconsますlist

clojure では、関数呼び出しとしてのみlists解釈されます。eval他のデータ構造とオブジェクトは、自己評価オブジェクトとして評価されます。

'(+ 3 4)に等しい(list '+ 3 4)です。'(リーダーによってquote関数に変換されます)与えられたフォームの評価を避けるだけです。そのため、in 式(eval '(+ 3 4)) evalはリスト データ構造('+ 3 4)を引数として取ります。

于 2012-12-27T00:59:18.230 に答える