---
# System prepended metadata

title: section6
tags: [macro]

---

---

title: section6
tags: macro

---

### 6 スプライシング・レットって何のためにあるの？

ラケット・スプライシングを一番長く見つめていました。何のために使うのか？なぜそれを使うのでしょうか？なぜリファレンスのマクロのセクションにあるのか？

ステップ1、~~箱に穴を開けて~~脱神話化する。例えば、splicing-letを次のように使います。

```ocaml=
> (require racket/splicing)
> (splicing-let ([x 0])
    (define (get-x)
      x))
; get-x is visible out here:
> (get-x)
0

; but x is not:
> x
x: undefined;

 cannot reference an identifier before its definition

  in module: 'program
```

は以下と同じです。

```ocaml=
> (define get-y
    (let ([y 0])
      (lambda ()
        y)))
; get-y is visible out here:
> (get-y)
0

; but y is not:
> y
y: undefined;

 cannot reference an identifier before its definition

  in module: 'program
```

これはLisp/Scheme/Racketの古典的なイディオムで、「let over lambda」と呼ばれることもあります。クロージャはyを隠し、yにはget-yでしかアクセスできないようになっています。

> クロージャとオブジェクトに関する公案です。

では、なぜスプライシング形式を気にするのでしょうか？特に複数のボディフォームがある場合、より簡潔にすることができます。

```ocaml=
> (require racket/splicing)
> (splicing-let ([x 0])
    (define (inc)
      (set! x (+ x 1)))
    (define (dec)
      (set! x (- 1 x)))
    (define (get)
      x))
```

スプライシングのバリエーションは、通常の方法よりも便利です。

```ocaml=
> (define-values (inc dec get)
    (let ([x 0])
      (values (lambda ()  ; inc
                (set! x (+ x 1)))
              (lambda ()  ; dec
                (set! x (- x 1)))
              (lambda ()  ; get
                x))))
```

体の形がたくさんあって、それをマクロで生成している場合は、バリエーションのつなぎ方がもっと簡単になります。

* [next section(7 堅牢なマクロ：syntax-parse)](https://hackmd.io/sCt8NNyTTc6XyPrCCaMIPw)

* [previous section(5 構文パラメータ)](https://hackmd.io/Hi_rX5oZTLKILvCF-QL6Lw)