6

新しい構文オブジェクトは、との両方で作成できますsyntax/locsyntaxこれも記述されてい#'ます)。

いつ使うべきsyntax/locですか?

4

1 に答える 1

6

またはでバインドされたパターン変数を参照している場合など、新しい構文オブジェクトを作成していない場合は#'(つまり)を使用します。syntaxsyntax-casewith-syntax

#'のように一時的な構文オブジェクトに使用します(syntax->list #'(id ...))

フォームに構文エラーがないことがわかっているフォームを表す構文オブジェクトに使用#'します。または、フォームの構文エラーがマクロの使用ではなく、マクロ実装の障害である場合に使用します。

syntax/locマクロの誤った使用による構文エラーを含む可能性のある式を作成する場合に使用します。

具体的な例を考えてみましょう。

フォームは、本体を評価する前にバインディングの値を表示することを除いて、display-let通常とまったく同じように機能する必要があります。let

これが最初の実装です:

(define-syntax (display-let-1 stx)
  (syntax-case stx ()
    [(_ ([id expr] ...) body ...)
     #'((lambda (id ...) 
          (displayln (format "~a is bound to ~a" 'id id)) ...
          body ...)
        expr ...)]))

マクロの正しい使用例を次に示します。

> (display-let-1 ([x 1] [y 2]) (+ x y))
x is bound to 1
y is bound to 2
3

ここで、マクロが正しく使用されていない場合に何が起こるかを見てみましょう。

> (display-let-1 ())
lambda: bad syntax in: (lambda ())

letの使用には常に空でない本文が必要であるため、この使用法は正しくありません。エラーメッセージを出力することに加えて、DrRacketはこのコードを赤に着色します。

(lambda (id ...) 
  (displayln (format "~a is bound to ~a" 'id id)) ...
  body ...)

lambdaマクロによって作成された式が正しくないことは正しいですが、(lambda ())正当ではありませんが、それはマクロのエラーによるものではなく、マクロの誤った使用によるものです。

非難をリダイレクトするには、構築されたlambda式をで囲み、syntax/locの最初の引数をsyntax/loc場所として使用して赤に着色します。

(define-syntax (display-let-2 stx)
  (syntax-case stx ()
    [(display-let ([id expr] ...) body ...)
     #`(#,(syntax/loc stx (lambda (id ...) body ...)) expr ...)]))

> (display-let-2 ())
display-let-2: bad syntax in: (display-let-2 ())

今回(display-let-2 ())は、replに入力されたものが赤で表示され、のdisplay-let-2代わりにエラーメッセージが表示されますlambda

于 2012-06-02T13:27:42.703 に答える