よーしパパ、関数に名前を付けずに再帰させちゃうぞぉ!(その2)

続き。
length0_2、length1_2、length2_2には依然として「あるパターンの繰り返し」が見える。
よし、これを取り除いていこうじゃないか、と。

  • L

何から始めればいいんだい?

  • R

引数としてlengthを取りlengthと同じような関数を返す関数に名前を付けるのさ。

(゚Д゚)ハァ?
意味わからん。んで、答えを見る。いつも見てr (ry
length0_2はこんな形に姿を変えるそうな。

;; length0_2を書き換えたやつ
(define length0_3
  ((lambda (mk-length)
     (mk-length eternity))
   (lambda (length)
     (lambda (l)
       (cond
        ((null? l) 0)
        (else (+ 1 (length (cdr l)))))))))

mk-lengthは「make length」の略だそうだ。
そっか、マイナスの記号は識別子に使えるんだったな。
フム、読めばなんとか理解できるけど絶対に書けねぇよ。
こいつも「無名関数を作ってその場で評価」ってパターンか。

(lambda (length) ...

以下がmk-lengthに渡されて、eternity(id:yagiey:20080323)がlengthに渡されて...
って、ぬぁんじゃこりゃ。頭がついていかんよ。
(「引数を渡す」とか「関数を実行する」なんて言葉はあんまり使いたくないけど、まだボキャ貧なのでスマソ)
しかし、まぁじっくり読むと結局出来上がる関数はlength0_0と同じなのが分かる。
んで、length1_2とlength2_2は以下のようになる。

;; length1_2を書き換えたやつ
(define length1_3
  ((lamda (mk-length)
     (mk-length
      (mk-length eternity)))
   (lambda (length)
     (lambda (l)
       (cond
        ((null? l) 0)
        (else (+ 1 (length (cdr l)))))))))

;; length2_2を書き換えたやつ
(define length2_3
  ((lambda (mk-length)
     (mk-length
      (mk-length
       (mk-length eternity))))
   (lambda (length)
     (lambda (l)
       (cond
        ((null? l) 0)
        (else (+ 1 (length (cdr l)))))))))


a-ha!!
凄いじゃないかマイケル!length1_2やlength2_2の

((lambda (f)
   (lambda (l)
     (cond
      ((null? l) 0)
      (else (+ 1 (f (cdr l)))))))
 再帰的な関数)

の部分がmk-lengthの評価で置き変わってるゾ!
ホントだぁパパ!これで随分コードが簡潔になったね!
mk-lengthの評価をネストしていけばどんなに長いリストでも長さを測れるぞマイケル!
やったね!パパ!


...というわけにはいかないか。まだ再帰関数とは言えないし。
どげんかせんといかん。