2回適用の組み合わせ方
次のような関数da
を考える。
(define ((da f) x) (f (f x)))
これが何をする関数なのか、日本語での説明を試みよう。
- fを受け取って、「xを受け取って、xにfを2回適用する関数」を返す関数
「〜を受け取って〜を返す関数」という言い方が入れ子になっていて、ちょっと分かりづらい。
動作例を示そう。
gosh> (define ((da f) x) (f (f x))) da gosh> (define not-not (da not)) not-not gosh> (not-not #f) #f gosh> (not-not #t) #t gosh> (not-not 1) #t
not-not
を適用すると、not
を2回適用したのと同じ値が返ってきているのが分かると思う。
もちろん、not-not
にda
を適用するのもアリ。not
の4回適用になる。
そうやって組み合わせていけば、n個のda
で2n回適用を作れることが分かると思う。
gosh> (define add1 (pa$ + 1)) add1 gosh> ((da (da (da (da (da (da (da (da (da (da add1)))))))))) 0) 1024
0にadd1
が210回適用されて、1024が返った。
ところで、da
自身にda
を適用することができる。
gosh> (((da da) add1) 0) 4 gosh> (((da (da da)) add1) 0) 16 gosh> (((da (da (da da))) add1) 0) 256 gosh> (((da (da (da (da da)))) add1) 0) 65536 gosh> (((da (da (da (da (da da))))) add1) 0) ; 65536^2 = 4294967296 が返るはずだけど……
n個のda
で、22n-1回適用になる。適用回数がどんどん自乗されていって、なかなかアグレッシブ。
さてさて、ここからが本題。実は、これ以上に激しい増え方をする組み合わせ方があるのだ。
gosh> (((da da) add1) 0) 4 gosh> ((((da da) da) add1) 0) 16 gosh> (((((da da) da) da) add1) 0) 65536 ; あれれ?
増え方がちょっとおかしいことに気づいてもらえただろうか。
24=16, 216=65536 ということなので、この次に
((((((da da) da) da) da) add1) 0)
とやれば265536となる。
n個のda
で2↑↑n回適用。たぶん最強。