3

コンパイル時のバインディングのためにマクロに特殊変数を挿入したいと思います。

たとえば、次の形式です。

(define-route (my/route)
  (some-proc @@request)
  (some-other-proc @@request))

次のように展開する必要があります。

(some-code)
...
(lambda (request)
  ...
  (some-proc request)
  (some-other-proc request))

request は、呼び出し元によって指定されたすべての場所で、生成されたコード内の request にバインドされます。

私はそれについて最善の方法がわかりません。これは、ラケット マクロが実行できる機能を提供するより一般的なパターンですか、それとも手動で行う必要がありますか?

もしそうなら、ボディ パターンを再帰的にループし、'@@request に一致するシンボルを探して、それらを置換する必要がありますか? syntax->list はこのように再帰的ではないことに気付きました。

(syntax->list #'(printf "first: ~a\" (get-var (other-proc)))

は 4 ではなく 3 つの構文オブジェクトであり、3 番目の構文オブジェクトはさらに 2 つです。したがって、ここで手動で繰り返す必要があると思いますが、これを行うためのより良い方法があるでしょうか?

ご協力いただきありがとうございます。

4

1 に答える 1

4

おそらく、syntax-parameterize (およびそのバリアントであるsplicing-syntax-parameterize ) を使用するとうまくいくのでしょうか? これは、キーワードのようなものが必要な場合や、マクロがコンテキストに基づいてキーワードの意味を再配線する必要がある場合の標準的なツールです。

外観は次のとおりです。

#lang racket/base

(require racket/stxparam
         racket/splicing
         (for-syntax syntax/parse racket/base))

(define-syntax-parameter @@request
  (lambda (stx)
    (raise-syntax-error #f "Use outside of a define-route" stx)))

(define-syntax (define-route stx)
  (syntax-parse stx 
    [(_ (name:id) body:expr ...)
     (syntax/loc stx
       (begin
         (printf "blah blah blah\n")

         (define name
           (lambda (request)
             (splicing-syntax-parameterize ([@@request
                                             (make-rename-transformer #'request)])
               body ...)))))]))

;; example
(define (f r)
  (printf "f sees: ~s\n" r))

(define-route (my/route)
  (f @@request))

(my/route 42)

構文パラメータ化は、によってバインドされているを参照@@requestするように、 のレキシカル コンテキストでの使用を再配線します。のコンテキスト外で使用すると、適切なエラー メッセージを表示しようとします。define-routerequestlambdadefine-route

(最初に計画した方法で、構文オブジェクトの構造を再帰的にたどり、要素を選択することもでき@@requestます。要件が本当に異常でない限り、これは必要以上の作業です。)

于 2013-01-14T23:26:58.453 に答える