Kullanmamanın birkaç nedeni vardır EVAL
.
Yeni başlayanların ana nedeni: buna ihtiyacınız yok.
Örnek (Common Lisp olduğu varsayılarak):
Bir ifadeyi farklı işleçlerle DEĞERLENDİRİN:
(let ((ops '(+ *)))
(dolist (op ops)
(print (eval (list op 1 2 3)))))
Daha iyi şöyle yazılır:
(let ((ops '(+ *)))
(dolist (op ops)
(print (funcall op 1 2 3))))
Lisp öğrenen yeni başlayanların ihtiyaç duyduklarını düşündükleri çok sayıda örnek vardır EVAL
, ancak buna ihtiyaç duymazlar - çünkü ifadeler değerlendirilir ve biri de işlev bölümünü değerlendirebilir. Çoğu zaman kullanımı EVAL
değerlendiricinin anlaşılmadığını gösterir.
Makrolarda da aynı sorun var. Yeni başlayanlar genellikle makrolar yazarlar, burada işlevler yazmaları gerekir - makroların gerçekte ne için olduğunu anlamadı ve bir işlevin zaten işi yaptığını anlamadı.
İşin kullanımı genellikle yanlış bir araçtır EVAL
ve genellikle yeni başlayanın normal Lisp değerlendirme kurallarını anlamadığını gösterir.
Eğer gerek düşünüyorsanız EVAL
, o zaman böyle olmadığını şeyi kontrol FUNCALL
, REDUCE
veya APPLY
bunun yerine kullanılabilir.
FUNCALL
- bağımsız değişkenleri olan bir işlevi çağırır: (funcall '+ 1 2 3)
REDUCE
- değerler listesindeki bir fonksiyonu çağırmak ve sonuçları birleştirmek: (reduce '+ '(1 2 3))
APPLY
- argüman olarak listelendiği bir işlevi çağırmak: (apply '+ '(1 2 3))
.
S: Gerçekten eval'e ihtiyacım var mı veya derleyici / değerlendirici gerçekten istediğim şeyi yapıyor mu?
EVAL
Biraz daha gelişmiş kullanıcılar için kaçınmanın ana nedenleri :
kodunuzun derlendiğinden emin olmak istersiniz, çünkü derleyici kodu birçok sorun için kontrol edebilir ve daha hızlı kod üretir, bazen ÇOK ÇOK ÇOK (bu faktör 1000 ;-)) daha hızlı kod
oluşturulan ve değerlendirilmesi gereken kod mümkün olduğunca erken derlenemez.
keyfi kullanıcı girişinin değerlendirilmesi güvenlik sorunlarını açar
ile değerlendirmenin bazı kullanımı EVAL
yanlış zamanda olabilir ve derleme problemleri yaratabilir
Son noktayı basitleştirilmiş bir örnekle açıklamak için:
(defmacro foo (a b)
(list (if (eql a 3) 'sin 'cos) b))
Yani, ya ilk parametreye dayalı bir makro yazmak isteyebilirsiniz SIN
veya COS
.
(foo 3 4)
yapar (sin 4)
ve (foo 1 4)
yapar (cos 4)
.
Şimdi sahip olabiliriz:
(foo (+ 2 1) 4)
Bu istenen sonucu vermez.
Daha sonra FOO
değişkeni DEĞERLENDİRerek makroyu onarmak isteyebilir :
(defmacro foo (a b)
(list (if (eql (eval a) 3) 'sin 'cos) b))
(foo (+ 2 1) 4)
Ama sonra bu hala çalışmıyor:
(defun bar (a b)
(foo a b))
Değişkenin değeri derleme zamanında bilinmemektedir.
Kaçınılması gereken genel bir önemli neden EVAL
: genellikle çirkin hack'ler için kullanılır.