新しい構文オブジェクトは、との両方で作成できますsyntax/loc
(syntax
これも記述されてい#'
ます)。
いつ使うべきsyntax/loc
ですか?
またはでバインドされたパターン変数を参照している場合など、新しい構文オブジェクトを作成していない場合は#'
(つまり)を使用します。syntax
syntax-case
with-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
。