Scheme修行14章

14章では新しく第15の戒律、letが出てきます。進むにつれて第14、第12の戒律を組み合わせて少しずつ奇麗なコードへ。
letccで得た方位磁針を渡してskipするなど前章とちょっとだけ違う使い方をしてるのも面白かったです。

気づいた点等、とりあえずメモ書き。

  • 同じ式が繰り返しでてくるのはまずい
    • 関数を理解するのに同じ式を2回読まないといけない
    • 関数を読んでる人が理解しづらいのと、2回評価するからその分計算が増えるからいけてない
  • 繰り返される式に名前をつけるためにletを使う
    • 再帰関数に名前をつけるのにはletrecを使う(以前の章でやった)
    • letrecは多分let recursiveの略、letは何の略かな?
    • letは以下のλ式シンタックスシュガー
      • (let ( (x1 α1) ... (xn αn)) β...)
      • ((lambda (x1 ... xn) β...) α1 ... αn)
      • λの仮引数x1...xnがα1...αnに束縛される
      • letrecは複数定義したのを相互に使えるけどletは駄目。
      • α1...αnを評価している環境の違いかな?
  • eqlist?はTheLittleSchemerでは自分で定義してた。(define eqlist? equal?)して代用。
  • letrecとletを使ってrember*を定義
    • avは何の略だろう?
  • 第15の戒律(仮)「繰り返される式の値に名づくるには(let ...)を用うべし。」
    • 「名づくる」「用う」初めて見た
  • rember1*を途中までrember*に空目してた
  • p70のdepth*は書き換えてテスト実行したけど確かに通らなかった
    • lが空か分かる前に(car l)の値に依存してしまっている
  • p73のdepthは非常に読みづらい
    • 1回しか評価されないのにletで名づくるのは読みづらくなったりする
  • 第15の戒律「関数定義において繰り返される式は、当の関数を1回使用するときに2回評価される可能性があるなら、それらの値を名づくるに(let ...)を用うべし。」
  • if文出てきた!
    • もっと前に知っておくべきだった?「何事にも、ふさわしい時と場所があるのです。」
    • (if α β γ)は(cond (α β) (else γ))と同じ
    • condを知ってればすっとifを理解出来る。
    • 答えによって2つに分かれる時ifを使うとcondよりも読みやすくなる
  • 最初のコードから掟に従いつつ構造を考えていくと可読性があがりますね
    • 比較するために1回、値を返すためにもう1回、合わせて2回評価してた
    • letで束縛すると2回評価しないでよくなってコードもすっきり
    • 2つに分岐するだけならifのがすっきり
    • やってることを抽象化してmaxを使えばすっきり
    • リファクタリングってこんな感じなのだろうか
  • letのbody部分に複数の式を置いてbegin的に使うなど
  • 「第14の戒律を用いるときに第13の戒律を忘れてはならない」
    • 関数を書き直していく時、今まで出てきた戒律を意識せねば。
  • letで順番よく実行している途中で答えを見つけたとき、抜け出すために方位磁針skipを使う
    • 継続を取り出してからマイナー関数に渡すことで、マイナー関数の中で値が求まった時に即座に返す事が出来る!
  • letccを使ったrember1*について
    • rember1*の中で、(car l)から何も取り除けなかったら方位磁針を使って戻って来る。
    • 取り除けた時はaを取り除いたリストを作りながら戻って来る。
    • 取り除けなかった時はnoっていうアトムを持って戻って来る。
    • 取り除けたら終わり、取り除けなかったらcdrで再帰
    • 方位磁針を使う事がないと分かっている場合は、0や'()を方位磁針として渡しても大丈夫。
  • tryを使うとちょうすっきり書ける。tryはマクロで書いた。
    • (try x a b)aの中でxを使うとaを抜けて、bを返す
    • 使わずにaを終了した場合、bは実行せず即座に値を返す

感想等

この章は結構ボリュームあった。休憩させるために「象を数えてみましょう。」とかそういうのが出て来るのが多かった気がする。
途中まではletの使い方で、2度評価される式に名前をつけたり、letをbeginのように使う使い方が出てきたり面白い。
後半数ページはletあまり関係なく継続の話だった。
引数でletccの方位磁針を受け取ったり、ifの条件式の中でletccを使うなど今までと違う使い方が出てきてこれもまた興味深い。
あと、tryを使うとなんだかものすっごいすっきり書けますね。

rmから結果を受け取って、rmの外側で成功したか判断して値を返すのではなく、
rm自身に失敗時の処理へ飛ぶ方位磁針を渡して渡しているのが面白い。
方位磁針を使わなかったら失敗時の処理へは飛ばず、rmの値が返る。
rmがその方位磁針を使うか使わないかをrmの内側で制御出来るようなイメージ。
方位磁針を使った時に返す値('no)をいじるともっと色々出来るのかな?
修行読みつつ(読み終わったら、になるかもしれないけど)プログラミングGauche読みます。

次の章への期待

この章まででかなり色々な関数の使い方を覚えました。
15章は表紙の絵だし、タイトルも「大人と子供の違い…」と、一区切り付きそうな印象。
時間をしっかり作りながら読んでいきたいと思います。
そういえば、バイト出始めたのでプライベートな時間ががくっと減って、働きながら勉強してって大変だなと思いました。
いつもおつきあい頂いてありがとうございます。 id:yamanetoshi となく!