Lisp在宏表达式中评估变量

时间:2013-10-25 21:16:26

标签: macros lisp elisp common-lisp clisp

我有以下功能(我是Lisp的初学者):

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

其中my-commandsend-and-reply-macro是另一个程序员编写的宏。我无法修改它。

my-commandsend-and-reply-macro将命令(在此示例中为cmd)发送到服务器进程(用另一种编程语言编写),然后等待其答案。 然后使用用户给定的“:代码的回复部分”在宏中处理答案。列表(ok结果)是一种模式,在宏中,destruct-bind解析并将答案的正确部分绑定到ok和result(ok只是一个标志)。在此之后,“:回复部分”的其他用户给定行被执行。 (用于结果处理)

我想做以下事情:

1,向其他进程发送命令(这没关系)

2,使用结果调用函数(比如do-something)并使用其他一些参数作为my-fun的实际参数(此部分失败......)

我该怎么做?我认为问题是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)))))

with-request-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)))

从另一个过程获得身份:

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

2 个答案:

答案 0 :(得分:1)

根本没有查看你的代码(道歉 - 没时间)---

函数a评估

bmy-fun 所有函数评估它们对 begin 的参数 - 只有宏和特殊形式不一定会评估它们的所有参数。

但那些ab未传递到宏 - 唯一传递给它的是未评估的 sexp 被绑定到cmd。而且你甚至没有在你的函数中定义cmd

您需要做的是将ab替换为cmd性别。您还没有展示如何定义/构建cmd。使用ab的值构建它,您应该没问题。

要构建cmd sexp,请记住您可以使用反引用语法来简化操作,使用逗号语法传递ab 。 E.g。

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

这假设您传递给宏的代码不需要变量 ab,并且只需要

答案 1 :(得分:1)

当调用函数my-fun时,参数已被评估,所以我不清楚你面临的问题是什么。

我看到的唯一奇怪的是宏是不卫生的,所以如果您的参数被命名而不是ab,例如statusstatus-args因为表达式

你会遇到麻烦
(do-something <a> <b> results)

将在宏中重用这些名称的上下文中编译。