Istnieje kilka powodów, dla których nie powinno się ich używać EVAL.
Głównym powodem dla początkujących jest: nie potrzebujesz tego.
Przykład (zakładając Common Lisp):
OCENA wyrażenia za pomocą różnych operatorów:
(let ((ops '(+ *)))
(dolist (op ops)
(print (eval (list op 1 2 3)))))
To lepiej napisać jako:
(let ((ops '(+ *)))
(dolist (op ops)
(print (funcall op 1 2 3))))
Istnieje wiele przykładów, w których początkujący uczący się Lispa myślą, że potrzebują EVAL, ale nie potrzebują tego - ponieważ wyrażenia są oceniane i można również ocenić część funkcji. W większości przypadków użycie EVALznaku wskazuje na brak zrozumienia ewaluatora.
Ten sam problem dotyczy makr. Często początkujący piszą makra, w których powinni pisać funkcje - nie rozumiejąc, do czego naprawdę służą makra i nie rozumiejąc, że funkcja już wykonuje swoje zadanie.
Często jest to niewłaściwe narzędzie do pracy EVALi często wskazuje, że początkujący nie rozumie zwykłych zasad oceny Lisp.
Jeśli uważasz, że potrzebujesz EVAL, sprawdź FUNCALL, REDUCEczy APPLYzamiast tego można użyć czegoś takiego lub .
FUNCALL - wywołaj funkcję z argumentami: (funcall '+ 1 2 3)
REDUCE - wywołaj funkcję na liście wartości i połącz wyniki: (reduce '+ '(1 2 3))
APPLY- wywołać funkcję z listy jako argumentów: (apply '+ '(1 2 3)).
P: Czy naprawdę potrzebuję eval, czy też kompilator / oceniający już to, czego naprawdę chcę?
Główne powody, których należy unikać w EVALprzypadku nieco bardziej zaawansowanych użytkowników:
chcesz mieć pewność, że Twój kod jest skompilowany, ponieważ kompilator może sprawdzić kod pod kątem wielu problemów i generuje szybszy kod, czasami DUŻO DUŻO (to współczynnik 1000 ;-)) szybszy kod
kod, który jest skonstruowany i musi zostać oceniony, nie może zostać skompilowany tak wcześnie, jak to możliwe.
ocena arbitralnych danych wejściowych użytkownika stwarza problemy związane z bezpieczeństwem
niektóre zastosowania ewaluacji EVALmogą się wydarzyć w złym czasie i spowodować problemy z kompilacją
Aby wyjaśnić ostatni punkt za pomocą uproszczonego przykładu:
(defmacro foo (a b)
(list (if (eql a 3) 'sin 'cos) b))
Więc może zechcę napisać makro, które na podstawie pierwszego parametru używa albo SINlub COS.
(foo 3 4)robi (sin 4)i (foo 1 4)robi (cos 4).
Teraz możemy mieć:
(foo (+ 2 1) 4)
Nie daje to pożądanego rezultatu.
Wtedy można chcieć naprawić makro FOO, oceniając zmienną:
(defmacro foo (a b)
(list (if (eql (eval a) 3) 'sin 'cos) b))
(foo (+ 2 1) 4)
Ale to nadal nie działa:
(defun bar (a b)
(foo a b))
Wartość zmiennej po prostu nie jest znana w czasie kompilacji.
Ogólny ważny powód, którego należy unikać EVAL: jest często używany do brzydkich hacków.