사용하지 말아야 할 몇 가지 이유가 있습니다 EVAL
.
초보자의 주된 이유는 필요하지 않기 때문입니다.
예 (공통 리스프 가정) :
다른 연산자를 사용하여 표현식을 평가하십시오.
(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
변수를 평가하여 매크로를 복구하려고 할 수 있습니다 .
(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
: 추악한 해킹에 자주 사용됩니다.