let-syntax と letrec-syntax フォームはキーワードを束縛する。 begin フォームと同様に、 let-syntax や letrec-syntax フォームは定義の文脈に現れることができ、その場合定義として扱われ、本体部分の中のフォームは定義でなければならない。 let-syntax や letrec-syntax は式の文脈にも現れることができ、その場合は本体部分中のふぉーむは式でなければならない。
構文: <bindings は次の形式をしていなければならない。
((<keyword> <expression>) ...)
各 <keyword> は識別子であり、各 <expression> は、マクロ展開時に、変換器に評価される式である。変換器は syntax-rules や identifier-syntax (R6RS:翻訳:R6RS:11.19 Macro transformers 参照)や R6RS:翻訳:Standard Libraries:12 syntax-case で述べられている他の仕組みのひとつで作成される。 <keyword> が束縛されるキーワードのリストの中に 2 回以上現れるのは構文違反である。
意味論: <form> は、キーワードが <keyword> であるマクロで、指定された変換器に束縛されたマクロで let-syntax の構文環境を拡張した構文環境で展開される。 <keyword> の各束縛は <form> をその領域とする。
let-syntax フォームの <form> は、定義の文脈でも式の文脈でも、暗黙の begin で囲まれているように扱われる。 R6RS:翻訳:R6RS:11.4.7 Sequencing 参照。したがって、 <form> を展開した結果の定義群は let-syntax が持つであろう領域の代わりに現れた定義と同一の領域を持つ。
実装系の義務: <expression> の値が変換器でないことを検知すべきである。
(let-syntax ((when (syntax-rules () ((when test stmt1 stmt2 ...) (if test (begin stmt1 stmt2 ...)))))) (let ((if #t)) (when if (set! if ’now)) if)) ⇒ now (let ((x ’outer)) (let-syntax ((m (syntax-rules () ((m) x)))) (let ((x ’inner)) (m)))) ⇒ outer (let () (let-syntax ((def (syntax-rules () ((def stuff ...) (define stuff ...))))) (def foo 42)) foo) ⇒ 42 (let () (let-syntax ()) 5) ⇒ 5
構文: let-syntax と同一である。
意味論: <form> は、キーワードが <keyword> であり、指定された変換器に束縛されたマクロで letrec-syntax の構文を拡張した構文環境で展開される。各 <keyword> の束縛は <form> と同様に <bindings> もその領域とする、そのため、変換器は letrec-syntax フォームで導入されたマクロの使用に展開することができる。
letrec-syntax フォームの <form> は、定義の文脈でも式の文脈でも、暗黙の begin で囲まれているように扱われる。 R6RS:翻訳:R6RS:11.4.7 Sequencing 参照。したがって、 <form> を展開した結果の定義群は letrec-syntax が持つであろう領域の代わりに現れた定義と同一の領域を持つ。
実装系の義務: 実装系は <expression> の値が変換器でないことを検知するべきである。
(letrec-syntax ((my-or (syntax-rules () ((my-or) #f) ((my-or e) e) ((my-or e1 e2 ...) (let ((temp e1)) (if temp temp (my-or e2 ...))))))) (let ((x #f) (y 7) (temp 8) (let odd?) (if even?)) (my-or x (let temp) (if y) y))) ⇒ 7
次の例は let-syntax と letrec-syntax がどのように異なるかを活写している。
(let ((f (lambda (x) (+ x 1)))) (let-syntax ((f (syntax-rules () ((f x) x))) (g (syntax-rules () ((g x) (f x))))) (list (f 1) (g 1)))) ⇒ (1 2) (let ((f (lambda (x) (+ x 1)))) (letrec-syntax ((f (syntax-rules () ((f x) x))) (g (syntax-rules () ((g x) (f x))))) (list (f 1) (g 1)))) ⇒ (1 1)
ふたつの式は最初の式の let-syntax フォームがふたつめでは letrec-syntax になっている以外同一である。最初の式では g 中に現れる f は let で束縛された変数を参照しているのに対して、ふたつめでは letrec-syntax フォームで束縛の確立されたキーワード f を参照している。