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を使うと個人的には少し読みにくい気もする。