我有以下功能(我是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))
答案 0 :(得分:1)
根本没有查看你的代码(道歉 - 没时间)---
函数a
评估 b
和my-fun
。 所有函数评估它们对 begin 的参数 - 只有宏和特殊形式不一定会评估它们的所有参数。
但那些a
和b
值未传递到宏 - 唯一传递给它的是未评估的 sexp 被绑定到cmd
。而且你甚至没有在你的函数中定义cmd
!
您需要做的是将a
和b
的值替换为cmd
性别。您还没有展示如何定义/构建cmd
。使用a
和b
的值构建它,您应该没问题。
要构建cmd
sexp,请记住您可以使用反引用语法来简化操作,使用逗号语法传递a
和b
的值 。 E.g。
(let ((cmd `(some funny (expression) that ((uses)) ,a AND ,b)))
code-that-uses-CMD)
这假设您传递给宏的代码不需要变量 a
和b
,并且只需要值
答案 1 :(得分:1)
当调用函数my-fun
时,参数已被评估,所以我不清楚你面临的问题是什么。
我看到的唯一奇怪的是宏是不卫生的,所以如果您的参数被命名而不是a
和b
,例如status
或status-args
因为表达式
(do-something <a> <b> results)
将在宏中重用这些名称的上下文中编译。