プログラミング言語 Scheme の構文である begin
は直列化のための機能としてよく理解されている。 要するに複数の式を順番に評価させる (そして最後の式の評価結果を全体の評価結果として返す) ための構文である。 Common Lisp の progn
に相当するものと説明されることもある。
だが、 begin
は状況によって別の解釈をされることがある。 R5RS の「5.1.プログラム」の項目で定義されているのだが、トップレベルに現れる begin
フォームに限っては、その内側に書かれている式、定義、構文定義と等価であるとされている。 つまり、 (begin a b c)
と書かれていたら、それはトップレベルに a b c
と書かれたのと同じになるということだ。
具体例で表してみよう。
(begin (define (plus-one x) (+ x 1)) (define (plus-two x) (+ x 2))) (write (+ (plus-one 1) (plus-two 1)))
このようにトップレベルの begin
の内側に書かれたものは以下と同等に解釈される。
(define (plus-one x) (+ x 1)) (define (plus-two x) (+ x 2)) (write (+ (plus-one 1) (plus-two 1)))
要するにトップレベルで begin
に囲まれている個所は囲まれていないのと同じであるということだ。 この操作を begin
の外側に「継ぎ合わせ (splicing)」られるという。 このことを知らないと begin
の内側での定義は一見してローカルな定義に見えてしまいがちなので注意が必要である。
囲んでも囲まなくても同じならわざわざ begin
で囲む意味などないだろうと思うかもしれないが、これは主にマクロへの配慮だと考えられる。 マクロはひとつのフォームを別のひとつのフォームに変換するものだが、複数のフォームへ変換したい場合もあるので見掛け上のひとつのフォームにするために begin
が必要なのだ。
ちなみに、 R6RS や R7RS ではこの継ぎ合わせはトップレベルだけでなく <body>
部で機能するように拡大されているのと、意味の異なる二種類の構文であることがより明確に書かれている。 また、 R7RS には define-library
の補助構文としての begin
もある (つまりは三種類の begin
がある)。 それらは同じ begin
という名前でありながらも現れる場所によって違う解釈されることには充分に注意が必要である。
Document ID: 0a54a00152f1c3e16c15ea8e11b1ea7b