2010年7月25日日曜日

[Squeak][VisualWorks] fold:

相変わらず,どうでもいいこと書きます.

http://lists.gforge.inria.fr/pipermail/pharo-project/2010-July/029669.html

fold:

foldと言われると,Squeakでは,inject:into:がすぐに思いつく.

#(1 2 3) inject:0 into:[:v1 v2 | v1 + v2 ].

Haskellでは
foldl (+) 0 [1, 2, 3]
Schemeでは
(fold + 0 '(1 2 3))

私のような初心者プログラマーは,初期値を考えるのが大変なので,ついつい,以下のようなコードを書いてしまいそうになってしまう.
array := Array with: 1 with: 2 with:3.
x := array first.
xs := array allButFirst.
xs inject:x into:[:v1 :v2 | v1 + v2 ].

このプログラムでは,allButFirstで,新たに配列を生成しているので,非効率.
やはり,きちんと初期値を決めなければなりません.

一方,Schemeでは,
gosh> (define array '(1 2 3))
gosh> (fold + (car array) (cdr array))
6

cdrは新たにリストを作成しているわけではないので,心配ありません.

それなら,初期値を考えていれればいいと言われる方もいると思いますが,これが意外と難しい.
例えば,配列の中から最大値を求めるのをinject:into:を書こうと思うと・・・.

array := Array with:-10 with:2 with:100.
array inject:  Float infinity negated into:[:v1 :v2 | v1 max: v2 ].
この場合は,マイナス無限大を初期値にする.


ちなみにVisualWorksでは,SequenceableCollection>>fold: が実装されている(さすが!).

array := Array with:1 with:2 with:3.
array fold:[:v1 :v2 | v1 + v2 ].

実装方法は,以下の通り.
SequenceableCollection>>fold: 
 | size nextValue |
 (size := self size) = 0 ifTrue: [^self emptyCollectionError].
  nextValue := self at: 1.
  2 to: size do:
  [:i | nextValue := binaryBlock value: nextValue value: (self at: i)].
  ^nextValue

先ほど,プログラムも簡単にかけます.

array := Array with:-10 with:2 with:100.
array fold:[:v1 :v2 | v1 max: v2 ].

ただし,SequenceableCollection>>fold: では,空のコレクションが与えられると,エラーになるので,注意が必要.エラーを発生させたくないなら,inject:into:を使うべき.
#() inject: 0 into:[:v1 :v2 | v1 + v2 ] "0が,かえってくる"

gosh> (fold +  0 '())
0

ふー,つかれた.

素人の意見としては,fold:が実装されるのは賛成.
みなさんはどう思われますか?



さらに,どうてもいいこと.

今回のでVisualWorksすごい!ってと思いましたが,Squeakユーザなので,操作がなかなか慣れない.

もともとHaskell,Schemeは,ほどんと書けなかったのですが,さらに書けなくなりましたorz

やっぱりReal Worldを購入すべきなのだろう.
英語本はもっているけど,読む時間がかかるので,やっぱり翻訳版を購入しようかな(でも高い・・・).
学生の頃に,翻訳本が出るとは思わなかったので,ついつい買ってしまった.

プログラミング言語の本を献本でもらえる人っていいなって思うけど,感想書くのが大変そう・・・.

0 件のコメント:

コメントを投稿