ようへいの日々精進XP

よかろうもん

2018 年 04 月 01 日(日)

ジョギング

  • 休み
  • 左足足底筋に強い張り

日課

  • 気付いたら, 日課も休んでた
  • まあイイや

禿げて (晴れて) 学生となった

修士科目生だけど, ソフトウェア工学を学びたくて入学した. 「入学のつどい」という入学式っぽいイベントに参加して, 学生証を貰ってきた.

inokara.hateblo.jp

「入学のつどい」の基調講演では「目先の利益選択が生む自滅的行動」というテーマで話を聴いたが, 身につまされるところがあって居眠りし辛かった.

アンクルった

「入学のつどい」からの帰り道, 喉が乾いたので香椎の「あんくるふじや」で一杯.

生一杯が 250 円なのでサイコーである.

今日のるびぃ ~ & と to_proc メソッド ~

引き続き, プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで の読書メモとググって得た知見をメモる.

モチベーション

こんなコードが...

irb(main):001:0> ['foo', 'bar', 'baz'].map {|s| s.upcase}
=> ["FOO", "BAR", "BAZ"]

以下のように書けるということが解って嬉しい.

irb(main):002:0> ['foo', 'bar', 'baz'].map(&:upcase)
=> ["FOO", "BAR", "BAZ"]

こちらの方がシンプルに書けるので, 利用していきたいと考えているが, なぜ, このような記述が可能なのかを第 10 章を読みつつ考察してみる.

proc オブジェクトをブロックとして渡したい場合

以下のように引数の前に & を付ける.

irb(main):002:0> upcase_proc = Proc.new { |s| s.upcase }
=> #<Proc:0x0055d1169582f0@(irb):2>
irb(main):005:0> ['foo', 'bar', 'baz'].map(&upcase_proc)
=> ["FOO", "BAR", "BAZ"]

& は以下のような役割がある.

  • Proc オブジェクトをブロックとして認識させる
  • & の後に渡されたオブジェクトに対して to_proc オブジェクトを呼び出し, その戻り値の Proc オブジェクトをブロックを利用するメソッドに渡す

以下のサンプルはこちらの記事を参考にさせて頂いた.

irb(main):001:0> def sample_method(param = nil)
irb(main):002:1>    return false unless block_given?
irb(main):003:1>    return true if block_given?
irb(main):004:1> end
=> :sample_method
irb(main):005:0> sample_method(Proc.new {})
=> false
irb(main):006:0> sample_method(&Proc.new {})
=> true
  • Proc インスタンスを引数として渡した場合, ブロックとしては渡されていない
  • Proc インスタンス& を付けてメソッドに渡すとブロックとして渡されている

to_proc メソッド

Proc オブジェクト以外でも, シンボルは to_proc が利用可能である. (その他に, Hash も to_proc を利用出来る)

irb(main):001:0> def sample_method(param = nil)
irb(main):002:1>    return false unless block_given?
irb(main):003:1>    return true if block_given?
irb(main):004:1> end
=> :sample_method
irb(main):007:0> sample_method(:a)
=> false
irb(main):008:0> sample_method(&:a)
=> true

ほうほう.

で, Enumerable#map と併用すると

冒頭に掲げた, Enumerable#map の引数として &:upcase を指定している場合, 以下のような処理の流れとなる.

  1. &:upcase:upcase に対して to_proc を呼び出す
  2. :upcase が Proc オブジェクトに変換されて map メソッドにブロックとして渡される
  3. 2 で作成された Proc オブジェクトは map メソッドによって評価される各要素の第一引数として受け取る (配列の各要素として upcase メソッドを呼び出す)

という流れで配列の各要素が大文字に変換され, 新しい配列に格納され map メソッドの戻り値となる.

irb(main):010:0> ['foo', 'bar', 'baz'].map(&:upcase)
=> ["FOO", "BAR", "BAZ"]

フムフム.

まだまだ, Proc に対する理解が足りないようだ.