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

続き。
length0_3とlength1_3とlength2_3に書き換えることで、結構コードも簡潔になった。
しかし、まだ「名前を付けずに再帰」という目標にはたどり着いてない。
なんとかせんとねー。

  • L

再帰ってどんなんよ?

  • R

mk-lengthを任意の関数へ無限に適用するみたいな感じやな。

  • L

ほんまに無限回適用せなあかんの?

  • R

んなあほな。
length(←いま作ろうとしている関数)を使うときはいつでも有限回の繰り返しでええよ。
せやけど、何回かはわからん。

  • L

なんぼmk-lengthが必要やったか想像できた?

ここら辺までは意味がつかめた。あとはサッパリ。(これは英語の問題。
ということで英語は早々にあきらめ、とりあえずソースコードを写経。
"Then is this still length0"って書いてあるから、たぶんlength0_*と同じ意味の関数なんだろう。
length0_4という名前にした。

(define length0_4
  ((lambda (mk-length)
     (mk-length mk-length))
   (lambda (length)
     (lambda (l)
       (cond
        ((null? l) 0)
        (else (+ 1 (length (cdr l)))))))))

とな。んで、Gaucheで評価してみる。

gosh> (length0_4 '())
0

まぁ、当然か。
んで、次が大事。空っぽじゃないリストを食わせてみるとどうなるのか実験。

gosh> (length0_4 '(hoge))
*** ERROR: operation + is not defined between 1 and #<closure (#f #f)>

とな。
「整数1と関数の間には+演算が定義されてないYO!!」って怒ってるっぽい。
eternityのときは「評価が終了しない」だったけど、mk-lengthに変えてから「エラーで止まる」という挙動に変わった。
ええのか?これで?
どこでエラーになってるのか調べてみよう。
...って、察しはつくけどね。eternityだった所のmk-lengthが関係してるんだろうな。たぶん。


orz

(mk-length mk-length)

みたいな、自分自身を引数にするとか意味わからんし。
このままじゃ自分の頭じゃ理解できなさそうなので、lambdaをなくしていく方向で変形していってみる。
とりあえず、

(lambda (length) ...

を適当にfと置いてみる。したらば、

((lambda (mk-length) (mk-length mk-length))
 f)

ってできる。さらにfを引数に、関数適用すると

(f f)

さらにfを展開すると、

((lambda (length)
   (lambda (l)
     (cond
      ((null? l) 0)
      (else (+ 1 (length (cdr l)))))))
 (lambda (length)
   (lambda (l)
     (cond
      ((null? l) 0)
      (else (+ 1 (length (cdr l))))))))

となる。なんか、どっかで見たことある形やな。
length0_2(id:yagiey:20080324)のeternityがlambda式に置きかわっとる感じだ。
...って、あたりまえか。
length0_3のeternityをmk-lengthに置換したからなぁ。
ということは、length0_2のeternityの部分をfで置き換えて書き直していくと、最終的にはlength0_4は

(lambda (l)
  (cond
   ((null? l) 0)
   (else
    (+ 1
       ((lambda (length)
          (lambda (l)
            (cond
             ((null? l) 0)
             (else (+ 1 (length (cdr l)))))))
        (cdr l)))))

となるはずやな。これやと、何処が何故エラーになるかすぐ分かる。
lengthは「1つ関数を引数として取る関数を返す関数」やもん。

(length (cdr l))

の部分は何らかの関数に評価される。
だから「数値の1と関数の間に+演算が定義されていない」というエラーなわけやな。


あー、横道にそれてばっかりで、なかなか進まん!
これだけグダグダ書いて1ページ分も進んでないし...。
ってか、未だにlambdaに慣れていない感じが否めない。
(ノ∀`)タハー