2013-10-25 96 views
1

評估變量我有以下功能(我在Lisp的一個非常初級):Lisp的宏表達

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

在我的-commandsend - 迴應 - 宏是由另一個程序員編寫的宏。我無法修改它。

my-commandsend-and-reply-macro向服務器進程(使用另一種編程語言編寫)發送命令(在本例中爲cmd),然後等待其答案。 然後在宏中使用用戶給定的「:代碼的回覆部分」處理答案。列表(OK結果)是一種模式,在宏中,解構綁定破壞並且將合適的答案綁定到ok和result(ok只是一個標記)。在此之後,「:回覆部分」的其他用戶給出的行被執行。 (對於結果處理)

我想做到以下幾點:

1,發送命令等發送到其他進程(這是確定)

2,調用一個函數(如做某事)使用結果和使用一些其他參數,這是我的樂趣的實際參數(這部分失敗...)

我該怎麼做?我認爲問題是a和b在宏擴展之前沒有被評估,當宏被擴展時Lisp搜索本地a和b,但是沒有a或b。有什麼方法可以評估a和b嗎? (這樣的宏可以像對待具體的值)

這是宏觀DEF:(由另一個程序員寫的)

(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))))) 

防守與請求-ID:

(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

你會更好地展示*宏(或其演示版本),而不僅僅是描述它。我真的不確定這是什麼意思:'發送像我這樣的命令(像做某事)n我的樂趣(這是好的)' – phils

+0

我同意@phils。試着展示你到目前爲止所嘗試的 - 確切的代碼。說出它發生了什麼,以及你期望/想要發生什麼。 – Drew

+0

正如我在我的問題中提到的,我嘗試使用「my-commandsend-and-reply-macro」和它的「:reply」部分來定義我自己的回調函數。在回調函數中,我需要使用一些變量(請參閱示例,如do-something中使用的變量「a」和「b」)。 發生了什麼:變量未被評估,並且Lisp表示沒有變量「a」或「b」(可能是動態作用域的原因),因爲它在宏擴展的位置搜索變量。 我想對此有一個解決方法。 – user1724641

回答

1

根本沒有查看您的代碼(道歉 - 沒有時間) ---

ab由函數評價。 全部功能評估它們的參數到開始只有宏和特殊形式不一定會評估它們的所有參數。

但這些ab不會傳遞到宏觀 - 傳遞給它的唯一的事情是未計算SEXP綁定到cmd。而且你甚至沒有在你的功能中定義cmd

你需要做的是替代abcmd SEXP。您還沒有展示如何定義/構建cmd。使用ab的值構建它,你應該沒問題。

要構建cmd SEXP,記住,你可以使用反引號語法把事情簡單化,用逗號語法傳遞ab。例如。

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

這是假設你傳遞給宏代碼不需要變量ab,而且只需要他們的

+0

或者''(let((cmd'(某...) ,a',b)))...)''。 –

+0

@WillNess - 是的,可能是這樣。 – Drew

1

當函數被調用時,參數已經被評估,因此我不清楚你面臨的問題是什麼。

我看到的唯一奇怪的是,宏是不衛生的,因此,如果你的論點被命名的ab代替例如statusstatus-args你會遇到麻煩,因爲表達式

(do-something <a> <b> results) 

將在這些名稱已被宏重用的上下文中進行編譯。