2012-03-23 3 views
3

나는 리스프에서리스트의 평가에 관한 질문이있다.Lisp에 의해 혼동 인용문

이유는 단지 (print 4) 같은

(defun test (a) (+ a 1)) 

여기에 평가되지 않습니다

(if (< 1 2) (print 3) (print 4)) 

하지만 (print (+ 2 3)) 그것은 뭔가가 있나요 여기

(test (print (+ 2 3))) 

을 평가, (a) 평가하지 (+ a 1)입니다 ~와 함께 표준 라이브러리 함수가 있습니까? Lisp 프로그램에서 이와 같은 함수를 정의 할 수 있습니까?

+0

[Lisp에서 '견적을 사용하는 경우] 가능한 복제본 (http://stackoverflow.com/questions/134887/when-to-use-quote-in-lisp) – sds

답변

5

아시다시피, Lisp 복합 양식은 일반적으로 바깥 쪽에서 처리됩니다. 양식을 이해하려면 가장 바깥 쪽 둥지의 첫 번째 위치에있는 기호를 봐야합니다. 이 기호는 양식의 의미를 완전히 결정합니다.

;; Common Lisp: define a class A derived from B and C 
(defclass a (b c)()) 

;; Common Lisp: define a function of two arguments 
(defun a (b c)()) 

;; add A to the result of calling function B on variable C: 
(+ a (b c)) 

전통적으로 Lisp 사투리는 연산자 형식과 함수 호출 형식으로 나누어 져 있습니다. 연산자 형식은 해당 함수를 컴파일하거나 해석하는 코드 조각에 의해 결정되는 완전히 임의의 의미를 지닙니다 (예 : 평가는 단순히 모든 함수 호출의 인수 양식에 대해 반복되고 그 결과 값은 함수로 전달됩니다).

초기 역사에서 Lisp은 사용자가 자신의 연산자를 작성할 수 있도록 허용했습니다.여기에는 해석 연산자 (역사적으로 fexprs으로 알려짐)와 매크로라고하는 연산자를 컴파일하는 두 가지 방법이있었습니다. 둘 다 논평되지 않은 형식을 인수로받는 함수 개념에 중점을 두어 사용자 지정 전략을 구현할 수 있으므로 평가 모델을 새로운 동작으로 확장 할 수 있습니다.

fexpr 타입 연산자는 변수의 값 등을 찾을 수있는 환경 객체와 함께 런타임에 양식을 간단히 넘깁니다. 그런 다음 해당 연산자는 양식을보고 해당 동작을 구현합니다.

매크로 연산자는 매크로 확장시 양식을 전달합니다 (일반적으로 최상위 양식을 평가하거나 컴파일하기 직전에 읽습니다). 그 일은 폼의 행동을 해석하는 것이 아니라 코드를 생성하여 폼을 해석하는 것입니다. 나는. 매크로는 미니 컴파일러입니다. (생성 된 코드는 더 많은 매크로 호출을 포함 할 수 있으며, 매크로 확장기는이를 처리하여 모든 매크로 호출이 데시 메이팅되도록합니다.)

fexpr 접근 방식은 비효율적이기 때문에 가능성이 떨어졌습니다. Lisp 해커가 컴파일을 중요시하는 반면 기본적으로 컴파일은 불가능합니다. (Lisp은 이미 1960 년 경부터 이미 컴파일 된 언어였습니다.) fexpr 접근법은 어휘 환경에 대해서도 적대적입니다. 어휘 스코프에서 허용되지 않는 일종의 캡슐화 위반 인 호출 된 양식의 변수 바인딩 환경에 피어링 할 수있는 함수 인 fexpr이 필요합니다.

매크로 쓰기는 fexprs보다 약간 어렵고 유연하지만 매크로 쓰기는 1960 년대에서 70 년대에 걸쳐 Lisp에서 가능한 한 쉽게 향상되도록 개선되었습니다. 매크로는 원래 전체 양식을받은 다음 자체적으로 구문 분석해야했습니다. 매크로 정의 시스템은 구문의 일부 중첩 된 측면을 포함하여 쉽게 소화 가능한 조각으로 구분 된 구문을받는 인수를 매크로 함수에 제공하는 것으로 개발되었습니다. 코드 템플릿을 작성하기위한 backquote 구문도 개발되어 코드 생성을 훨씬 쉽게 표현할 수 있습니다.

질문에 대답하기 위해 어떻게 저와 같은 양식을 작성할 수 있습니까? 예를 들어 경우 : 원래 리스프 만 cond 있었기 때문에

;; Imitation of old-fashioned technique: receive the whole form, 
;; extract parts from it and return the translation. 
;; Common Lisp defmacro supports this via the &whole keyword 
;; in macro lambda lists which lets us have access to the whole form. 
;; 
;; (Because we are using defmacro, we need to declare arguments "an co &optional al", 
;; to make this a three argument macro with an optional third argument, but 
;; we don't use those arguments. In ancient lisps, they would not appear: 
;; a macro would be a one-argument function, and would have to check the number 
;; of arguments itself, to flag bad syntax like (my-if 42) or (my-if).) 
;; 
(defmacro my-if (&whole if-form an co &optional al) 
    (let ((antecedent (second if-form)) ;; extract pieces ourselves 
     (consequent (third if-form)) ;; from whole (my-if ...) form 
     (alternative (fourth if-form))) 
    (list 'cond (list antecedent consequent) (list t alternative)))) 

;; "Modern" version. Use the parsed arguments, and also take advantage of 
;; backquote syntax to write the COND with a syntax that looks like the code. 
(defmacro my-if (antecedent consequent &optional alternative) 
    `(cond (,antecedent ,consequent) (t ,alternative)))) 

이 피팅 예입니다. McCarthy 's Lisp에는 if이 없었습니다. 그 "통용 설탕"은 나중에 my-if과 같이 cond으로 확대되는 매크로로 나중에 만들어졌습니다.

6

ifdefun은 매크로입니다. 매크로는 양식을 더 긴 코드로 확장합니다. 확장시 매크로의 인수는 평가되지 않습니다.

함수를 작성하려고하지만 사용자 정의 평가 전략을 구현해야하기 때문에 어려움을 겪으면 매크로 대신 매크로를 작성해야한다는 강력한 신호가 나옵니다.

면책 조항 : 사용하는 릭 종류에 따라 ifdefun은 기술적으로 매크로가 아닌 "특수 형식"이라고 할 수 있지만 지연 평가의 개념은 여전히 ​​적용됩니다.

1

Lisp은 양식 평가 모델로 구성됩니다. 다른 Lisp 방언은 그것들에 대해 다른 규칙을 가지고있다.

Common Lisp을 살펴 보겠습니다.

  • 데이터 자체
  • 에 함수 형태
  • 특별한 형태의 각 특수 조작에 정의 된 규칙에 따라 평가되는 평가 인자의 함수를 호출하여 평가 평가한다. Common Lisp 표준은 이들 모두를 나열하고 비공식적 인 방식으로 사용자 정의를 정의하며 사용자가 새 특수 연산자를 정의 할 수있는 방법은 없습니다.
  • 매크로 형태의 결과가

를 평가, 변환되는 방법 IF, DEFUN 등의 작품과 어떤이 doen 때 그들은 평가하고 무엇을 평가하지 않는 커먼 리스프 표준에 정의되어 있습니다.