R6RS:翻訳:R6RS:11.2 Definitions

R6RS:翻訳:R6RS:11.2 Definitions

11.2 定義

定義は <top-level body> (R6RS:翻訳:R6RS:8 Top-level programs)の内部、ないしは <library body> (R6RS:翻訳:R6RS:7.1 Library form)や <body> (R6RS:翻訳:R6RS:11.3 Bodies)に出現する。

<definition> は変数定義(11.2.1 節)かキーワード定義(11.2.2)節である。定義に展開されるマクロの使用や、(begin、 let-syntax、 letrec-syntax フォームでまとめられた――R6RS:翻訳:R6RS:11.4.7 Sequencing 参照)定義は他の定義の現れるところにはどこにでも現れる可能性がある。

11.2.1 変数定義

本節で述べる define フォームは <definition> であり、変数の束縛をつくるために使われ、他の定義が現れる場所にはどこにでも現れる可能性がある。

[syntax] (define <variable> <expression>)

[syntax] (define <variable>)

[syntax] (define (<variable> <formals>) <body>)

[syntax] (define (<variable> . <formals>) <body>)

define の最初の形式は <expression> の値を新しい場所に代入する前に <variable> をそこに束縛する。

(define add3
  (lambda (x) (+ x 3)))
(add3 3)                                    ⇒  6
(define first car)
(first ’(1 2))                              ⇒  1

<expression> の継続は 2 回以上起動されてはならない。

実装系の義務: 実装系は <expression> の継続が 2 回以上起動することを検知するべきである。実装系がこれを検知した場合、 &assertion コンディション型の例外を発生させなければならない。

2 番目の形式は次と等価である。

(define <variable> <unspecified>)

ここで、<unspecified> は副作用のない未規定値を返す式である。

3 番目の形式では、 <formals> は 0 個以上の変数の並びか、 0 個以上の変数の並びにドット . と別の変数が続いたものでなければならない(lambda 式と同様に。R6RS:翻訳:R6RS:11.4.2 Procedures 参照)。これは次と等価である。

(define <variable>
  (lambda (<formals>) <body>))

4 番目の形式では、 <formal> は単一の変数でなければならない。これは次と等価である。

(define <variable>
  (lambda <formal> <body>))

11.2.2. 構文定義

本節で述べる define-syntax フォームはキーワードの束縛を作るのに使われる <definition> であり、他の定義の現れられるところならどこにでも現れることができる。

[syntax] (define-syntax <keyword> <expression>)

<keyword> を <expression> に束縛する。 <expression> はマクロ展開時に展開器に評価されなければならない。マクロ展開器は R6RS:翻訳:R6RS:11.19 Macro transformers で述べる syntax-rules と identifier-syntax で作成することができる。より完全な変換器の説明については R6RS:翻訳:Standard Libraries:12.3 Transformers を参照。

define-syntax により確立されたキーワード束縛は、 define により確立された変数束縛とちょうど同じように、他の束縛により隠蔽された場合を除き、その現れた本体部分で可視であり、他の部分ではそうではない。定義の集合により確立された束縛は、キーワード定義であれ変数定義であれ、定義自体の内部で可視である。

実装系の義務: 実装系は <expression> の値が変換器でない可能性について検知しなければならない。

例:

(let ()
  (define even?
    (lambda (x)
      (or (= x 0) (odd? (- x 1)))))
  (define-syntax odd?
    (syntax-rules ()
      ((odd?  x) (not (even? x)))))
  (even? 10))                               ⇒ #t

処理順序が左から右であることから(R6RS:翻訳:R6RS:10 Expansion process)ひとつの定義が後続のフォームが定義もあるかどうかに影響を与えることがある。

例:

(let ()
  (define-syntax bind-to-zero
    (syntax-rules ()
      ((bind-to-zero id) (define id 0))))
  (bind-to-zero x)
  x)         ⇒ 0

この振る舞いは let 式の外側に現れる bind-to-zero の束縛には影響を受けない。

More ...