1

私は次の機能を持っています(私は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))
4

2 に答える 2

1

関数my-funが呼び出されると、引数はすでに評価されているため、直面している問題が何であるかはわかりません。

私が見る唯一の奇妙なことは、マクロが非衛生的であるため、引数がaandの代わりに名前が付けられているb場合、statusまたはstatus-args式が原因で問題が発生することです。

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

これらの名前がマクロによって再利用されたコンテキストでコンパイルされます。

于 2013-10-27T18:27:37.683 に答える