2013-10-25 1 views
1

에서 변수를 평가하고 난 다음 함수 (나는 리스프에서 아주 초보)가 내-commandsend 및 회신 - 매크로 다른 프로그래머가 작성한 매크로입니다리스프 매크로 표현

(defun my-fun (a b) 
    (my-commandsend-and-reply-macro (cmd) 
     (:reply (ok result) 
       (do-something a b result))) 
) 

. 수정할 수 없습니다.

my-commandsend-and-reply-macro는 명령 (이 예제에서는 cmd)을 서버 프로세스 (다른 프로그래밍 언어로 작성 됨)로 보내고 응답을 기다립니다. 답변은 사용자가 지정한 ": 코드의 응답 부분"을 사용하여 매크로에서 처리됩니다. 목록 (ok 결과)은 일종의 패턴이며, 매크로에서는 destructuring-bind가 응답의 올바른 부분을 소멸시키고 바인드하여 ok와 result를 반환합니다 (ok는 단지 플래그 임). 이 후에 ": reply 부분"의 다른 사용자 지정 줄이 실행됩니다. 같이 할 무언가 (

1, 함수를 호출 (이 괜찮)

이 다른 프로세스에 다음과 같은 명령을 보내

(결과 처리) 나는 다음을 수행 싶습니다) 결과를 사용하고 내 재미의 실제 매개 변수 인 다른 일부 매개 변수를 사용합니다 (이 부분은 실패합니다 ...)

어떻게하면됩니까? 문제는 a와 b가 매크로 확장 전에 평가되지 않고 매크로가 확장되면 Lisp은 로컬 a와 b를 검색하지만 a 나 b가 없다는 것입니다. a와 b를 평가할 방법이 있습니까? (다른 프로그래머에 의해 작성)을 요청-ID의

(defmacro* my-commandsend-and-reply-macro ((cmd &rest args) &body body) 
`(progn 
    (with-request-id() 
    (setf (gethash *request-id* *my-callbacks*) 
     (lambda (status &rest status-args) 
      (case status 
      ,@(loop for (kind . clause) in body when (eql kind :reply) 
       collect 
       (destructuring-bind 
        ((status-flag &rest lambda-form-pattern) 
            &body action-given-by-user) clause 
        `(,status-flag 
         (destructuring-bind ,lambda-form-pattern status-args 
         ,@action-given-by-user)))) 
      ((error) 
       (message "Error: %s" (elt (elt status-args 0) 1)))))) 
       (apply #'send-command-to-process *request-id* cmd args))))) 

정의 : :

(defmacro* with-request-id ((&rest vars) &body body) 
    "Send `getid' to the server, and call `body' once the response 
with the new ID has arrived. By then, global variable `*request-id*' 
is bound to the latest request ID." 
`(progn 
    (when (not (server-is-running)) 
     (error "Server isn't running!")) 
    (when *reqid-queue* 
     (error "Some internal error occured. Please, restart the program!")) 
    (lexical-let (,@(loop for var in vars 
         collect `(,var ,var))) 
    (setf *reqid-queue* (lambda() 
         (unwind-protect 
          (progn ,@body) 
          (setf *reqid-queue* nil))))) 
    (get-id))) 

그리고

이 매크로 데프이다 (그래서 매크로 콘크리트 값처럼 취급 할 수) 다른 프로세스에서 ID를 얻는 중 :

(defun get-id() 
    (send-command-to-process 'getid)) 
+1

매크로를 설명하려고하는 것보다 매크로를 표시하는 것이 더 낫습니다 (또는 실증적 인 버전). 그리고 나는 이것이 무엇을 의미하는지 정말로 확신하지 못합니다 :'나는 (무언가와 같은) 명령을 내 재미로 보내십시오. (이것은 괜찮습니다.) ' – phils

+0

나는 @phils에 동의합니다. 지금까지 시도한 것을 정확한 코드로 보여줍니다. 그걸로 어떻게되는지, 그리고 그 대신에 당신이 기대하고/원하는 것을 말하십시오. – Drew

+0

제 질문에서 언급했듯이 "my-commandsend-and-reply-macro"와 ": reply"부분을 사용하여 내 자신의 콜백 함수를 정의하려고했습니다. 콜백에서 나는 어떤 변수를 사용할 필요가있다. (do-something에 사용 된 my-fun의 변수 "a"와 "b"같은 예제를 보라). 어떤 일이 일어나는가 : 변수는 평가되지 않으며 Lisp는 매크로가 펼쳐진 곳을 찾기 때문에 변수 "a"또는 "b"(아마도 동적 범위 지정의 원인이 될 수 없음)가 없다고 말합니다. 이 문제에 대한 해결 방법이 필요합니다. – user1724641

답변

1

코드를 전혀 보지 않고 (사과 - 시간 없음) ---

ab함수 my-fun 평가이다. 모두 함수는 자신의 인수를 begin으로 평가합니다. - 매크로 및 특수 형식 만이 모든 인수를 평가하지는 않습니다.

하지만 그 ab 값은 매크로에를 전달되지 않습니다 - 전달 된 유일한 cmd에 바인딩 된 평가되지 않은 sexp입니다. 그리고 함수에 cmd을 정의하지 않았습니다.

은 무엇 당신이해야 할 것은 cmd sexp에 ab을 대체합니다. cmd이 정의/구축 된 방법을 전혀 보여주지 않았습니다. ab의 값을 사용하여 구성하면 OK입니다.

ab를 전달하는 쉼표 구문을 사용하여, 당신이 일을 단순화 역 인용 부호 구문을 사용할 수있는 기억의 cmd sexp를 구성합니다. 예 :

(let ((cmd `(some funny (expression) that ((uses)) ,a AND ,b))) 
    code-that-uses-CMD) 

이 매크로에 전달하는 코드가 변수ab을 필요로하지 않는다는 것을 가정하고는 자신의 이 필요합니다.

+0

또는 아마도''(let ((cmd {(some ... ' , a ', b))) ...)''. –

+0

@WillNess - 가능합니다. – Drew

1

함수 이 호출되면 인수가 이미 평가되었으므로 사용자가 직면 한 문제가 무엇인지 명확하지 않습니다.

내가 볼 수있는 유일한 이상한 점은 매크로가 해제 위생과 인수가 예를 status 또는 status-args에 대한 ab 대신에 이름을 지정하는 경우 그래서 당신 표현

(do-something <a> <b> results) 
때문에 문제가 될 겁니다 때문이다

은 해당 이름이 매크로에 의해 다시 사용 된 컨텍스트에서 컴파일됩니다.