Scheme修行15章

Scheme修行は毎章違う題材が出てきます。前の章の継続も面白かったけど今回のも面白い。

メモ等

  • ここに来て初めてdefineで値に名前をつける。
  • set!の読み方「セット、バン!」
  • set!は値を返さない。defineと似たもの。Lispではsetq(セットキュー、説得)
  • set!すると名前の参照を変更出来る。あたかもxが定義されてないときにdefineで名前をつけるように。
  • lambdaの値部分に2つ式があるのはletやbeginと同じ。2番目の式(最後の式)の値を返す。
  • 別々の関数で同じ名前に対してset!する衝突が起こりえる。それは困る。
  • lambdaをletで囲む
    • あたかも架空の名前x1をdefineしたかのよう
    • 架空の名前の値はない。
    • 架空の名前が何を表しているか覚えておかないといけない
  • 16の戒律「(let...)で定義された名前に対してのみ、(set!...)を使うべし
    • 大域的な名前にset!すると駄目
  • 第17の戒律(予備版)

(let ( (x ...)) ...)に対して(set! x ...)を用いる際には
それらの間には少なくとも1つのlambdaを置くべし

  • letとsetの間にlambdaを入れないで使っても何かを覚える役には経たない
  • 第18の戒律「(set! x ...)はxが参照する値がもはや必要ないときにのみ使うべし」
    • set!すると値への参照がなくなってしまうので。
    • swapを例に
    • letを使って名前をつけるとその値を参照するのに2通りの方法がある

感想

15章ではset!の使い方と破壊的代入の問題点を説明している感じがしました。
ふつーのプログラミング入門だと変数に値を入れるのが関数の定義よりも先に来ますよね。
Scheme手習い、Scheme修行ではアトムから始まって、すぐに関数を定義して、値は引数で取り、関数を組み合わせて抽象化し、わざわざ関数に名前をつけずともY Combinaterがあれば再帰が出来る事を示し、計算結果を覚えるためにletを使い、と、ここまで値にdefineで名前をつける必要がありませんでした。
set!の説明と問題点を示すためだけにdefineで値に名前をつけている気がします。
関数プログラミング的な考えが重用視されてるような感じをちょっと受けています。
次の章が楽しみです。set!の上手い使いどころを示してくれそうな感じ。

# ホワイトボード使ってやるのも楽しそうですね

※ところでこの章、試験なナニを書けない気がします。なので実行ログを残しました。

gosh> (define x
        (cons 'chicago
              (cons 'pizza '())))
x
gosh> x
(chicago pizza)
gosh> (set! x 'gone)
gone
gosh> x
gone
gosh> (set! x 'skins)
skins
gosh> (define gourmet
        (lambda (food)
          (cons food (cons x '()))))
gourmet
gosh> x
skins
gosh> (cons x '())
(skins)
gosh> (gourmet 'onion)
(onion skins)
gosh> (set! x 'rings)
rings
gosh> (gourmet 'onion)
(onion rings)
gosh> (define gourmand
        (lambda (food)
          (set! x food)
          (cons food (cons x '()))))
gourmand
gosh> (gourmand 'potato)
(potato potato)
gosh> x
potato
gosh> (gourmand 'rice)
(rice rice)
gosh> x
rice
gosh> (define diner
        (lambda (food)
          (cons 'milkshake (cons food '()))))
diner
gosh> (define dinerR
        (lambda (food)
          (set! x food)
          (cons 'milkshake (cons food '()))))
dinerR
gosh> (dinerR 'onion)
(milkshake onion)
gosh> x
onion
gosh> (dinerR 'pecanpie)
(milkshake pecanpie)
gosh> x
pecanpie
gosh> (gourmand 'onion)
(onion onion)
gosh> (define omnivore
        (let ((x 'minestrone))
          (lambda (food)
            (set! x food)
            (cons food (cons x '())))))
omnivore
gosh> 'minestrone
minestrone
gosh> (omnivore 'bouillabaisse)
(bouillabaisse bouillabaisse)
gosh> (define gobbler
        (let ((x 'minestrone))
          (lambda (food)
            (set! x food)
            (cons food (cons x '())))))
gobbler
gosh> (gobbler 'gumbo)
(gumbo gumbo)
gosh> (define nibbler
        (lambda (food)
          (let ((x 'donut))
            (set! x food)
            (cons food (cons x '())))))
nibbler
gosh> (nibbler 'cheerio)
(cheerio cheerio)
gosh> (define food 'none)
food
gosh> (define glutton
        (lambda (x)
          (set! food x)
          (cons 'more (cons x (cons 'more (cons x '()))))))
glutton
gosh> (glutton 'garlic)
(more garlic more garlic)
gosh> food
garlic
gosh> x
onion
gosh> (define chez-nous
        (lambda ()
          (set! food x)
          (set! x food)))
chez-nous
gosh> food
garlic
gosh> x
onion
gosh> (chez-nous)
onion
gosh> food
onion
gosh> x
onion
gosh> (define chez-nous
        (lambda ()
          (let ((a food))
            (set! food x)
            (set! x a))))
chez-nous
gosh> (glutton 'garlic)
(more garlic more garlic)
gosh> food
garlic
gosh> (gourmand 'potato)
(potato potato)
gosh> x
potato
gosh> (chez-nous)
garlic
gosh> food
potato
gosh> x
garlic
gosh> 

リポジトリの方にもcommitしてるのですが、外出先からPDA Net使ってgit pushしようとしたのですが繋がらないため、GitHubの同期はちょっと遅れてしまいそうです。ごめんなさい。