2013-10-16 2 views
5

나는 lisp 함수에 전달 된 값이 매개 변수 이름과 일치하는 견적에 할당되었다고 가정했습니다. 그러나 나는 이렇게 놀랐다 :함수 매개 변수는 어떻게 lisp에 저장됩니까?

(defun test (x) (print (eval 'x))) 
(test 5) 

(변수 x는 언 바운드 임). 따라서 매개 변수가 함수의 기호로 저장되지 않으면이 예제에서 정확히 IS x는 무엇입니까? 매개 변수 이름과 일치하는 기호에서 매개 변수에 액세스하는 방법이 있습니까?

더 많은 상황 :

defun slice (r1 c1 r2 c2 board) 
    (dolist (param '(r1 c1 r2 c2)) ;adjust for negative indices 
    (if (< (eval param) 0) 
     (set param (+ (length board) (eval param))))) 
     ;Body of function 

는 기본적으로, 나는 그들이 <을 경우 그 값의에 처음 네 개의 매개 변수를 통해 반복하고 조정을 할 : 내가하고 싶은 무엇 이 같은 것입니다 물론, 나는 let을 할 수 있고 각 매개 변수에 대해 개별적인 행을 가질 수 있지만,이 4 개의 매개 변수 각각에 대해 똑같은 일을한다고 생각하면 이것은 더 깔끔하게 보입니다. 그러나 변수 R1이 바인딩되지 않았다는 오류가 발생합니다.

+0

그것은 특정 구현 :

한 가지 방법은 자신이 매크로 것이 반복하지 않도록합니다. [SBCL] (http://www.sbcl.org/manual/index.html)에서는 Foreign Function Interface 장 등에 몇 가지 정보를 제공합니다. –

답변

4

매개 변수 이름과 일치하는 기호에서 매개 변수에 액세스하는 방법이 있습니까?

어휘 바인딩이 아닙니다. Common Lisp은 비슷한 이름의 심볼에서 어휘 변수에 접근하는 방법을 제공하지 않습니다. 변수 으로 선언해야합니다.

매개 변수가 함수에 기호로 저장되지 않은 경우이 예제에서 정확히 IS x은 무엇입니까?

프로세서 레지스터? 스택 프레임의 일부입니까? 동적 바인딩으로

:

CL-USER 40 > (defun foo (a b) 
       (declare (special a b)) 
       (dolist (v '(a b)) 
       (if (zerop (symbol-value v)) 
        (set v 10))) 
       (values a b)) 
FOO 

CL-USER 41 > (foo 1 0) 
1 
10 
+0

감사합니다. 이렇게하면 단 한 줄만 추가하면 동일한 코드를 사용할 수 있습니다 특수 매개 변수 – rcorre

+2

@murphyslaw 변수를 선언 할 때 발생할 수있는 다른 결과를 이해했는지 확인하십시오. 변수는 동적 범위에 바인딩됩니다. 예를 들어'(let ((x 3)) (declare (special x)) (funcall (let xx 4)) (declare (special x)) (lambda) x))))''람다 '함수가 생성 될 때'x'가'4'에 바인드 되더라도'4'가 아닌'3'을 반환합니다. –

+0

@ JoshuaTaylor - 머리를 가져 주셔서 감사합니다. 분명히 이것에 대해 더 읽어야합니다. 확실하게, 매개 변수를 특수 문자로 선언하면 함수 블록 외부의 심볼에 아무런 영향을 미치지 않을 것입니다. 맞습니까? – rcorre

2

라이너가 설명했듯이, 당신은 그것의 이름으로 어휘 인수 값에 액세스 할 수 없습니다.

은 당신이 대신 할 수있는 것은 당신이 너무 변수를 원하는 경우 destructuring-bind와 함께 &rest 인수를 사용할 수 있습니다 : 변수 이름은 직접으로 어휘 범위 내에서 대체됩니다 : 기본적으로 어떻게 어휘 바인딩 작품이다

(defun slice (board &rest params) 
    (destructuring-bind (r1 c1 r2 c2) 
     (mapcar (lambda (param) ;adjust for negative indices 
       (if (minusp param) 
        (+ (length board) param) 
        param)) 
       params) 
    ... operate on r1 c1 r2 c2 ...)) 
5

변수의 값이 저장된 위치를 참조하십시오. 변수 이름의 symbol-value 바인딩은 special으로 선언 할 수있는 동적 변수에 대해서만 수행됩니다.

(defmacro with-adjusting ((&rest vars) adjust-value &body body) 
    `(let ,(loop for var in vars 
       collect `(,var (if (minusp ,var) 
           (+ ,var ,adjust-value) 
           ,var))) 
    ,@body)) 

(defun slice (r1 c1 r2 c2 board) 
    (with-adjusting (r1 c1 r2 c2) (length board) 
    ;; function body 
+1

좋은 답변입니다. 매크로는 여기에서 매우 유용합니다. 작은 단점 : 컴파일 된 코드가 커집니다. –

관련 문제