2012-02-11
■RubyのEnumerable#mapをもっと便利にしたいよ
次のような名前のリストがあって
langs = ["ruby", "python", "lisp", "haskell"]
名前の先頭を大文字にするとしたら
君ならどうする?
そう普通Enumerable#mapを使って
次のようにするよね
langs = ["ruby", "python", "lisp", "haskell"] langs.map { |lang| lang.capitalize } # => ["Ruby", "Python", "Lisp", "Haskell"]
Enumerable#mapってほんと死ぬほど便利だよ
僕はRubyの魅力の80%は
mapが占めてるんじゃないかって
たまに感じることがあるよ.. :)
でもただ先の例で
大文字にするだけなのにブロックって
ちょっと大げさすぎると思わない?
もちろんそうなんだよ
そう思うRubyistが沢山いたから
mapは次のように書けるようにもなってるんだ
langs = ["ruby", "python", "lisp", "haskell"] langs.map(&:capitalize) # => ["Ruby", "Python", "Lisp", "Haskell"]
シンボルに&を付けてmapに渡すと
暗黙的にSymbol#to_procが呼ばれて
そこで配列の各要素にcapitalizeが適用されるよ
この記法のお陰でmapは一層使い勝手が良くなってるよ
じゃあ今度は先の言語名のリストから
その「言語使いのリスト」に変換してほしいんだけど..
つまり言語名の後に'ist'を付けてほしいんだ*1
そう次のようにするよね
langs = ["ruby", "python", "lisp", "haskell"].map(&:capitalize) langs.map { |lang| lang + 'ist' } # => ["Rubyist", "Pythonist", "Lispist", "Haskellist"]
これって悔しいよね
'ist'を足すだけなのに
またブロックを書かなきゃいけない
同じように次のような場合も
ブロックを書かなきゃいけない
[1, 2, 3].map { |i| i + 10 } # => [11, 12, 13] (1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25] [[1,2,3,4], [5,6,7,8], [9,10,11,12]].map { |arr| arr.last(2) } # => [[3, 4], [7, 8], [11, 12]] ["ruby", "python", "lisp", "haskell"].map { |lang| lang[-2, 2] } # => ["by", "on", "sp", "ll"]
僕はすごく悔しいよ..
そんなわけで..
Enumerable#mappを考えたよ!
module Enumerable def mapp(op=nil, *args, &blk) op ? map { |e| op.intern.to_proc[e, *args]} : map(&blk) end end langs.mapp(:+, 'ist') # => ["Rubyist", "Pythonist", "Lispist", "Haskellist"]
その引数が取れるんだ
[1, 2, 3].mapp(:+, 10) # => [11, 12, 13] (1..5).mapp(:**, 2) # => [1, 4, 9, 16, 25] [[1,2,3,4], [5,6,7,8], [9,10,11,12]].mapp(:last, 2) # => [[3, 4], [7, 8], [11, 12]] ["ruby", "python", "lisp", "haskell"].mapp(:[], -2, 2) # => ["by", "on", "sp", "ll"]
ブロックを渡せばmapに処理を投げるから
mapの代わりとしても使えるよ
[1, 2, 3].mapp { |i| i + 10 } # => [11, 12, 13] (1..5).mapp { |i| i**2 } # => [1, 4, 9, 16, 25] [[1,2,3,4], [5,6,7,8], [9,10,11,12]].mapp { |arr| arr.last(2) } # => [[3, 4], [7, 8], [11, 12]] ["ruby", "python", "lisp", "haskell"].mapp { |lang| lang[-2, 2] } # => ["by", "on", "sp", "ll"]
誰でも考えそうだから
既出のアイディアだったらゴメンね
って
もっと高度なことをまめさんがしてました^^;
まあ折角書いたから..
ゴメンナサイm(__)m
関連記事:RubyのSymbol#to_procを考えた人になってみる - hp12c
(追記:2012-2-14)Twitterを通してすごい荒業を知ったよ*2
[1,2,3].map(&1.method(:+)) #=> [2,3,4]
スゴイね!
でもメソッド呼び出しのオブジェクトが
引数と入れ替わっちゃってるから:+, :*くらいしか
用途がなさそうだけどね..
- 43 http://www.kt.rim.or.jp/~kbk/zakkicho/
- 34 http://www.kt.rim.or.jp/~kbk/zakkicho/index.html
- 14 http://reader.livedoor.com/reader/
- 12 http://wayohoo.com/ios/news/100yen-ipod-touch-stand.html
- 6 http://blog.livedoor.jp/dankogai/archives/51764496.html
- 5 http://127.0.0.1:4474/top?3119232
- 5 http://www.google.co.jp/url?sa=t&rct=j&q=ansi color&source=web&cd=6&ved=0CEQQFjAF&url=http://d.hatena.ne.jp/keyesberry/20101107/p1&ei=MX82T_zKDYrKmQWn4aCMAg&usg=AFQjCNGBXx5OB-XLOmqGp2DPIzMnbch3Iw&sig2=MiidA3exjfYwozY1qkDb6A
- 5 http://www.google.com/search
- 4 http://bit.ly/xtvBAQ
- 4 http://t.co/YByk4pIq
