Rubyの要点
Rubyを使っていて、自分の理解が浅かったところをまとめてみました。
map,reduce,filter
Lispなどの関数型言語でお馴染みの上記関数をRubyで使う。
map
rubyにもmapメソッドがあります。 実際はcollectというメソッドの別名ですが、mapを使うほうが混乱は少ないかな。
list = (1..10) list.map{|i| i*2} #listの全要素を2倍します
reduce
これもinjectというメソッドの別名です。
list = (1..10) list.reduce {|sum,n| sum+n} #すべての要素を足し合わせる
filter(=select)
Haskellなどで使われるfilterメソッドに対応するのはselectというメソッドです。
list = (1..10) list.select{|n| n % 3 == 0} #3の倍数を抽出する
ブロック
do 〜 end(または{〜})で囲まれた部分。 メソッドの引数として使われる。
mapを実装してみる。
list = (1..10) # 特異メソッドを使ってlistのインスタンスにmap2を実装 def list.map2(&block) new_list = [] self.each do |i| new_list << block.call(i) end new_list end list.map2{|i| i*2} => [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
&blockでブロック引数を受け取っている。
&はブロックをProcオブジェクトに変換するための記号。
(ブロック自体はオブジェクトとして存在できず引数として渡せないのでこのような方法をとるらしい)
ただ、この書き方は冗長である。なぜなら・・
「ブロック引数は仮引数の中で一番最後に渡されなければならない」
という制約があるから。
つまり、引数自体宣言する必要ないんじゃね?ということ。
このためRubyにはyield(イールド)という構文が用意されている。
これを使えばブロック引数の宣言すら必要ない。こんな感じでかけちゃう・・・
# yieldを使って書き直す def list.map3() new_list = [] self.each do |i| new_list << yield(i) end new_list end
ただ、yieldを使うと個人的には少し読みにくい気もする。