Existem várias razões pelas quais não se deve usar EVAL.
A principal razão para iniciantes é: você não precisa disso.
Exemplo (assumindo Common Lisp):
AVALUE uma expressão com diferentes operadores:
(let ((ops '(+ *)))
(dolist (op ops)
(print (eval (list op 1 2 3)))))
Isso é melhor escrito como:
(let ((ops '(+ *)))
(dolist (op ops)
(print (funcall op 1 2 3))))
Existem muitos exemplos em que os iniciantes que aprendem o Lisp acham que precisam EVAL, mas não precisam - já que as expressões são avaliadas e também é possível avaliar a parte da função. Na maioria das vezes, o uso de EVALmostra falta de entendimento do avaliador.
É o mesmo problema com macros. Geralmente, os iniciantes escrevem macros, onde devem escrever funções - sem entender para que servem as macros e sem entender que uma função já faz o trabalho.
Geralmente, é a ferramenta errada para o trabalho usar EVALe geralmente indica que o iniciante não entende as regras usuais de avaliação do Lisp.
Se você acha que precisa EVAL, em seguida, verificar se algo assim FUNCALL, REDUCEou APPLYpoderia ser usado em seu lugar.
FUNCALL - chame uma função com argumentos: (funcall '+ 1 2 3)
REDUCE - chame uma função em uma lista de valores e combine os resultados: (reduce '+ '(1 2 3))
APPLY- chamar uma função com uma lista de argumentos: (apply '+ '(1 2 3)).
P: Eu realmente preciso de avaliação ou o compilador / avaliador já é o que realmente quero?
Os principais motivos a serem evitados EVALpara usuários um pouco mais avançados:
você deseja garantir que seu código seja compilado, porque o compilador pode verificar se há muitos problemas e gerar um código mais rápido, às vezes MUITO MUITO MUITO (o fator 1000 ;-)) código mais rápido
o código que é construído e precisa ser avaliado não pode ser compilado o mais cedo possível.
avaliação de entrada arbitrária do usuário abre problemas de segurança
algum uso da avaliação EVALpode ocorrer no momento errado e criar problemas de compilação
Para explicar o último ponto com um exemplo simplificado:
(defmacro foo (a b)
(list (if (eql a 3) 'sin 'cos) b))
Então, talvez eu queira escrever uma macro que, com base no primeiro parâmetro, use SINou COS.
(foo 3 4)faz (sin 4)e (foo 1 4)faz (cos 4).
Agora podemos ter:
(foo (+ 2 1) 4)
Isso não fornece o resultado desejado.
Pode-se reparar a macro FOOEVALuating a variável:
(defmacro foo (a b)
(list (if (eql (eval a) 3) 'sin 'cos) b))
(foo (+ 2 1) 4)
Mas isso ainda não funciona:
(defun bar (a b)
(foo a b))
O valor da variável simplesmente não é conhecido no momento da compilação.
Um motivo geral importante a ser evitado EVAL: geralmente é usado para hacks feios.