酔って適当に考えたことを書き留めておく

半分以上与太だけど、ツッコミ歓迎

SICPは「計算機プログラムの構造と解釈」というコンピュータサイエンスの教科書です。サンプルはすべてSchemeというLispの方言で書かれています。以下、「本当にプログラミング未経験でSICPから入門しようとする人」が陥るかもしれない三つの罠を挙げてみます。

1. 破壊的代入に対する嫌悪感を植えつけられる SICPには「大リーグボール養成ギプス」のような側面があります。ストイックな制限を与えることで思考の流れを誘導する感じ。第1章ではリストが使えず（LISP＝LISt Processingなのに！）、第2章まではset!が使えないため破壊的代入ができません。つまり状態が扱えない（実際には2章の最後のほうではテーブルが最初から用意されていることにしてオブジェクト指向っぽいことをしてますが）。第3章でようやく状態を扱えるようになりますが、「状態ってめんどくさいよねー」という例がさんざん出てきた挙句、最後に「遅延ストリームがあれば代入はなくてもよくね？」という展開。プログラミング経験がある人はだまされないと思いますが、真っ白な状態から入った人はたぶん破壊的代入が生理的に嫌いになります。というか私はなりました。おそらくSICPの目的の一つは関数型スタイルへの洗脳です。 ただ、オブジェクト指向プログラミングをはじめ、普通のプログラミングでは状態を普通に使います。当然。破壊的代入がイヤだと駄々をこねるのは現実的ではありません。遅延評価やモナドを持つHaskelにそのままなだれ込めば幸せな人生を送れるのかもしれませんが、ALGOL系の言語を全く知らずにHaskelのコードをバリバリ書いている人には、私はいまだにお目にかかったことはありません。 ということで、何事にも限度というものはあるのです。

2. ループが嫌いになる Schemeで繰り返し構造を書く方法は再帰しかありません（というのは少しウソですが）。必然的にSICPのサンプルは再帰だらけです。リスト操作ではmapのような高階関数も多用しますが、ちょっと凝ったことをしようとすると再帰、再帰です。再帰は慣れるまでにちょっとした壁はありますが、慣れると書くのが楽しくなります。もしかしたらRubyの楽しさに似ているのかもしれません（私はRubyistではないのでよくわかりませんが）。再帰を利用すると、ただのループでは書くのが面倒な、込み入った場合分けなどを簡潔に記述できます。 再帰はスタックを消費するので普通は避けたほうがよいとされていますが、Schemeでは末尾再帰は最適化される（リソースを消費しない）と決まっています。なので、Schemeプログラマは再帰を多用すると同時に、自然に末尾再帰で書くようになります。とはいえ、なんてことない繰り返しまでループではなく再帰で書きたがるのは問題です。こうした姿勢はScheme以外の「標準でループが用意されている言語」ではリソースの無駄遣い、つまり明らかに有害です。 繰り返しますが、何事にも限度というものはあるのです。