星田さんの記事に対するコメント。
いや、それは当然「使えません」。
この部分の定義は、結果、
(define (next-pit w)
(let* ((snake (pit-snake w))
(goos (pit-goos w))
(goo-to-eat (can-eat snake goos)))
(if goo-to-eat
(pit (grow snake) (age-too (eat goos goo-to-eat)))
(pit (slither snake) (age-goo goos)))))
と書いてるのと同じなんで、goo-to-eatは局所変数、なのでレキシカルスコープの働きで考えれば外部からはアクセス不可、です。
単にローカル変数とeat関数の仮引数の名前が同じなだけ、ですね(仮引数の名前は何でも良い、から)。
eat関数はnext-pit関数の中で使われているんで、同名の仮引数を使って明確化してる、ってのが本当のトコでしょう。
一応、ある程度書いて一回runしちまえば、デバッグの一種なんだけど、DrRacketはどの変数がどの変数を受け取ってるのか、マウスオーバーで知らせてくれる筈です。
そうしたら、外部に変数が読まれてることはない、ってのが視覚的に分かると思います。
長い仮引数名って面倒だと思ってたけど、snとか短いのじゃなくて読んですぐに理解できるものにすべきですね
そう、エディタに自動補完機能さえあれば長い名前は一向に構わない、んです。どんなに長くても「選択」-> 「リターン」でO.K.なんで。
まぁね、DrRacketはさすがに自動補完やってくれる程高機能じゃないんで。
言い換えると、Emacsをはじめ、人々は何故にIDEに行くのか、と言うと自動補完が結果美味しくて見た目にも分かりやすいから、ですよね。
後は・・リストの最後を消すって処理でいつものnull?で調べるんじゃなくてCDR LISTで空リストを返すようにするってのも地味におお・・って感じ。
ちなみに、それもANSI Common Lisp由来の関数ですね。地味に役立つ関数なのに、何故かSchemeには含まれてない・・・・・・。
要するに逆順にした時のcarの効果、とcdrの効果みたいなモノ、ってんで、Racketにはlastはあるけど、but-lastにあたる関数がやっぱ用意されてないんで自作せなアカン、って例ですね。
その関数は末尾再帰で書けば
(define (all-but-last segs)
(let loop ((segs segs) (acc '()))
(let ((seg (rest segs)))
(if (empty? seg)
(reverse acc)
(loop seg (cons (first segs) acc))))))
なんだけど、もっと直接的に書けば結果、
(define (all-but-last segs)
(reverse (rest (reverse segs))))
と、反転させてcdrを取ってまた反転するだけで終わり。
まぁ、その章のテーマが「再帰」なんで、敢えて再帰で書いてる、ってトコかな・・・・・・。
あと、Racetって[リストを入れてるとコッカの部分で)を連打しても対応してるところはちゃんと]に自動で入力されるんですね!それが出来るなら色を自動で変えるのもやってくれれば良いのにw
ホンマそう(笑)。
あと、自動補完も欲しいよなぁ、正直なトコ・・・・・・。
結構DrRacketって「見た目も良いIDE」なんだけど、ちょっと痒いとこに手が届かないトコがある・・・・・・。