プログラミング再入門

プログラミングをもう一度ちゃんと勉強する読書ノート

Scheme修行 第12章 避難しましょう(その2)

letrecを使った既出の関数の再定義が続きます。

ノート:

union

member?のおさらい。ラットの中に指定のアトムが含まれていれば#t。そうでなければ#f。

letrecを使って再帰の際にaを渡さない版が定義出来る。関数名のyes?はあまりしっくり来ない。また、letrecの値としてyes?を返している版とlatにyes?を適用した値を返している版が紹介されている。

unionのおさらい。関数の値はset2を基本とし、set1のある要素がset2に含まれていれば値に加える。和集合となる。

> (let ((set1 '(tomatoes and macaroni casserole))
        (set2 '(macaroni and cheese)))
    (union set1 set2))
(tomatoes casserole macaroni and cheese)
> 

letrecを使った版をunion2として定義。評価してみる。

> (let ((set1 '(tomatoes and macaroni casserole))
        (set2 '(macaroni and cheese)))
    (union2 set1 set2))
(tomatoes casserole macaroni and cheese)
> 

letrecにmember?も取り込んだ版をunion3として定義。評価してみる。

> (let ((set1 '(tomatoes and macaroni casserole))
        (set2 '(macaroni and cheese)))
    (union3 set1 set2))
(tomatoes casserole macaroni and cheese)
> 

member?に毎回渡しているaをN?を導入する事で省いた版をunion4として定義。評価してみる。

> (let ((set1 '(tomatoes and macaroni casserole))
        (set2 '(macaroni and cheese)))
    (union4 set1 set2))
(tomatoes casserole macaroni and cheese)
> 
two-in-a-row

two-in-a-row-bの様な補助関数を関数内部に定義。

> (two-in-a-row '(a b c d e f f g))
#t
> (two-in-a-row '(a b c d e f g))
#f
> 

最初にtwo-in-a-rowが受け取るlatはWに取っては必要の無い情報なのでWからはアクセス出来ない様にする方が良い。まずletrecで補助関数を定義し、letrecの最初の式をlambda (lat)とする事でWのスコープから最初のlatを外す事が可能。
two-in-a-row2として定義して評価してみる。

> (two-in-a-row2 '(a b c d e f f g))
#t
> (two-in-a-row2 '(a b c d e f g))
#f
> 
sum-of-prefixes

(+ sss (car tup))の重複は何とかならないものか。

> (sum-of-prefixes '(1 2 3 4 5))
(1 3 6 10 15)
> 
scramble

ここでもscramble-bをletrecでscramble内で定義。評価してみる。

> (scramble '(1 1 1 3 4 2 1 1 9 2))
(1 1 1 1 1 4 1 1 1 9)
> (scramble '(1 2 3 4 5 6 7 8 9))
(1 1 1 1 1 1 1 1 1)
> (scramble '(1 2 3 1 2 3 4 1 8 2 10))
(1 1 1 1 1 1 1 1 2 8 2)
> 

補助関数の名前は定義を短くする為には短い(一文字)が良いのかもしれないが、個人的には定義の中身を読み下さないとその関数が何をやるのか理解出来ないので極力意味のある名前の方が良い気がする。
また、Schemeでは基本的に述語には?が付いているのでtwo-in-a-row内部のW等も?が付いているべきだと思う。