私は次の機能を持っています(私は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) をサーバー プロセス (別のプログラミング言語で記述されています) に送信し、その応答を待ちます。回答は、ユーザーが指定した ":reply コードの部分" を使用してマクロで処理されます。リスト (ok 結果) は一種のパターンです。マクロでは、destructuring-bind が分解し、答えの適切な部分を ok と結果にバインドします (ok は単なるフラグです)。この後、":reply 部分" の他のユーザー指定の行が実行されます。(結果処理用)
私は次のことをしたいと思います:
1、他のプロセスに同様のコマンドを送信します(これで問題ありません)
2、結果と my-fun の実際のパラメーターである他のパラメーターを使用して (do-something のような) 関数を呼び出します (この部分は失敗します...)
これどうやってするの?問題は、マクロ展開の前に 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)))
そして、他のプロセスからIDを取得します:
(defun get-id ()
(send-command-to-process 'getid))