2006年05月20日 09:30 [Edit]

mapとはおれのことかとcollectいい

孫引き失礼。

map派だなぁ。 @ 2006年05月 @ ratio - rational - irrational @ IDM
るびま
Enumerable#collect を主に使う派閥と Enumerable#map を主に使う派閥があり (これらのメソッドは効能および用法用量が同じ)、互いに血で血を洗う派閥抗争に明け暮れている

同じくmap。つーか、perlにはそっちしかないじゃん(藁)


と聞くと、あとgrepとselectはどうよ?という質問が考えられるのだけど、こちらはrubyでは明白に違うんだよねえ。ちなみにperlのgrepはrubyのselectの方。

あと、rubyにもperlにもないlispishなbuiltinに、applyがある。rubyの方は「ない」と言い切れるほどのrubyistでは私はないのだけど、少なくともEnumerableを見る限り、なさげ。どんなものかと言うと、perl5でやるとこんな。

use strict;
use warnings;
use utf8;

sub apply(&@){
    my $subref = shift;
    my $retval = shift;
    for my $operand (@_){
        $retval = $subref->($retval,$operand);
    }
    return $retval;
}

binmode STDOUT, ":utf8";
my $Σ = apply { $_[0]+$_[1] } (1..10);
my $Π = apply { $_[0]*$_[1] } (1..10);
print "Σ(1..10)=$Σ,Π(1..10)=$Π\n";

Javascriptにはapplyがちゃんとあるし、Perl6ではさらにReduce Operatorというさらに洗練されたものが存在する上、オレ演算子も思いのまま作れる。

sub prefix:<Σ> (@v) { [+] *@v};
sub prefix:<Π> (@v) { [*] *@v};

まあ見てのとおり、簡単に定義できるものだけど、builtinでないのはちょっとした謎かも。

Dan the Anonymous Operator

追記: Perlでも標準モジュールのList::Utilreduce()が存在します。こちらの方の実装では、$_[0],$_[1]ではなく、sort()と同じく$a,$bを使っていますがやっていることは同じです。rubyのEnumerable#injectはコメント欄参照。


この記事へのトラックバックURL

この記事へのトラックバック
前回の記事にも書きましたが、今期から私はテニス部の副顧問になることが決まりました。顧問になるとプライベートな時間が大幅に無くなるので・・・
教えがいがあるってもの【奈保美】at 2006年05月21日 02:33
この記事へのコメント
上の sendTo は send でした。ごめんなさい。

masao さん、
inject ではブロックの評価値が sum に代入されるのでブロック内での明示的な代入は必要ありません。(そうしないと、inject って感じが出ませんし…(^_^;))

$ irb
>> (1..10).inject{|sum,e| sum+e }
=> 55

Dan さん、
Ruby の inject は、Smalltalk の #inject:into: が名前と振る舞いの元になっています。
Posted by sumim at 2006年05月20日 12:08
LISP/Scheme の apply は、Ruby では sendTo、Smalltalk では #perform:withArguments: のほうが気持ち的には近いかもしれませんね。

$ gosh
gosh> (string-append "abc" "def")
"abcdef"
gosh> (apply string-append '("abc" "degf"))
"abcdegf"

$ irb
>> "abc" + "def"
=> "abcdef"
>> "abc".send(:+, "def")
=> "abcdef"

"Squeak(Smalltalk)"
'abc', 'def' " => 'abcdef' "
'abc' perform: #, withArguments: #('def') " => 'abcdef' "
Posted by sumim at 2006年05月20日 12:00
masaoさん、
ああ、なるほど。Enumerable#inject も紹介しとくべきでしたね。
でも、semtanticsが違いすぎて、applyと同じ事をやっても、同じと見なすには抵抗があります。第一引数がmemoですから(これはこれで使いでがある。一般的なapplyでは、+=とか*=は使えない)。
でも、なんでinjectなの?
Dan the Occasional Rubyist
Posted by at 2006年05月20日 11:40
これ?

irb> (1..10).inject{|sum,e| sum+=e }
=> 55
irb> (1..10).inject{|sum,e| sum*=e }
=> 3628800
Posted by masao at 2006年05月20日 11:32