2005/07/28

いまさら気が付いたしょうもないこと。Scheme と Haskell では fold の動作が違うんですね……
どちらもこんな風に書くわけだけど(Haskellの場合は foldl)、

fold proc 種 (x_1 x_2 ... x_n)

これが Scheme では

proc (x_n ... (proc x_1 種)...)

と評価されるのに対し、Haskell では

proc (...(proc 種 x_1) ... x_n)

とみなされる。

「種とリストの要素のどちらを先に proc に渡すか」が正反対なので、除算みたいな可逆でない演算の場合に思い悩む。

gosh-rl> (fold / 128 '(8 4 2))
0.03125

Hugs.Base> foldl (/) 128 [8,4,2]
2.0

この例では Haskell のほうが感覚にマッチするなあ。Scheme で Haskell と同じことがしたい場合には無名関数を使うしかないのかしらん。

gosh-rl> (fold (lambda (x y) (/ y x)) 128 '(8 4 2))
2


なんでこんなことが気になったかというと、情報処理学会誌6月号の Haskell の数当てゲームの記事に、0~9 の自然数からなるリストを各数字が各桁に対応する1つの自然数に移す関数 pack: (a b c ..) → abc.. が foldl で実装されていたから。こんなやつ。

Hugs.Base> foldl (\ x y -> 10 * x + y) 0 [1,2,3]
123

上記のような理由で、これをそのまま Scheme に置き換えても期待した結果は得られない。

gosh-rl> (fold (lambda (x y) (+ (* 10 x) y)) 0 '(1 2 3))
60

lambda 内の x と y を逆にすればいいだけなんだけどさ。

No comments :