使用すべきでない理由はいくつかありますEVAL
。
初心者の主な理由は、あなたがそれを必要としないことです。
例(Common Lispを想定):
異なる演算子を使用して式を評価します。
(let ((ops '(+ *)))
(dolist (op ops)
(print (eval (list op 1 2 3)))))
それは次のように書く方が良いです:
(let ((ops '(+ *)))
(dolist (op ops)
(print (funcall op 1 2 3))))
Lispを学ぶ初心者EVAL
が必要だと考える例はたくさんありますが、式は評価され、関数の部分も評価できるため、必要ではありません。ほとんどの場合、の使用はEVAL
評価者の理解の欠如を示します。
マクロでも同じ問題です。多くの場合、初心者は関数を書くべき場所でマクロを書く-マクロが本当に何のためにあるのかを理解しておらず、関数がすでに仕事をしていることを理解していない。
それはしばしばジョブが使うための間違ったツールでありEVAL
、それはしばしば初心者が通常のLisp評価ルールを理解していないことを示しています。
あなたが必要と考えられる場合はEVAL
、何かのような場合は、チェックFUNCALL
、REDUCE
またはAPPLY
代わりに使用することができます。
FUNCALL
-引数を指定して関数を呼び出します。 (funcall '+ 1 2 3)
REDUCE
-値のリストに対して関数を呼び出し、結果を結合します。 (reduce '+ '(1 2 3))
APPLY
-リストを引数として関数を呼び出します(apply '+ '(1 2 3))
。
Q:私は本当にevalを必要としますか、それともコンパイラ/エバリュエータはすでに私が本当に望んでいるものですか?
EVAL
やや上級のユーザーには避けるべき主な理由:
コンパイラはコードの多くの問題をチェックし、より高速なコードを生成できるため、コードがコンパイルされていることを確認したい場合があります。
構築され、評価が必要なコードは、できるだけ早くコンパイルできません。
任意のユーザー入力を評価すると、セキュリティの問題が発生します
評価の一部の使用はEVAL
、間違ったタイミングで発生し、ビルドの問題を引き起こす可能性があります
簡単な例で最後のポイントを説明するには:
(defmacro foo (a b)
(list (if (eql a 3) 'sin 'cos) b))
したがって、最初のパラメーターに基づいてSIN
またはを使用するマクロを記述したい場合がありますCOS
。
(foo 3 4)
し(sin 4)
、(foo 1 4)
します(cos 4)
ます。
今私たちは持っているかもしれません:
(foo (+ 2 1) 4)
これは望ましい結果を与えません。
次にFOO
、変数をEVALuateすることでマクロを修復することができます。
(defmacro foo (a b)
(list (if (eql (eval a) 3) 'sin 'cos) b))
(foo (+ 2 1) 4)
しかし、これはまだ機能しません:
(defun bar (a b)
(foo a b))
変数の値は、コンパイル時には不明です。
避けるべき一般的な重要な理由EVAL
:醜いハッキングによく使用されます。