ようへいの日々精進XP

よかろうもん

2018 年 02 月 14 日(水)

ジョギング

  • お昼休みを利用して香椎浜 x 2 周
  • 背中が痛くて呼吸がとてもつらいランニングだった

日課

  • (腕立て x 50 + 腹筋 x 30) x 3

夕飯

  • 「よしもと」で 1000 円セット
  • オーナーに新メニューをおまけしてもらう

バレンタイン

  • バレンタインデイということで, 奥さんがデッカイプリンを 2 つ買ってきた
  • ほとんど奥さんが食べて, 食べ過ぎで気分が悪くなっていた

今日のるびぃ ~ yield と Proc (2) ~

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

ブロックを引数として受け取る

  • ブロックを引数として受け取る場合は, 引数名の前に & を付ける
  • ブロックを実行する場合は call メソッドを利用する
[1] pry(main)> def greeting(&block)
[1] pry(main)*   block.call('foo')  
[1] pry(main)* end  
=> :greeting
[2] pry(main)> 
[3] pry(main)> greeting do |text|
[3] pry(main)*   puts text  
[3] pry(main)* end  
foo
=> nil
  • 引数名は自由で付けることが出来る
  • 他の引数がある場合, 最後に指定する必要がある
[4] pry(main)> def greeting(arg, &b)
[4] pry(main)*   p arg
[4] pry(main)*   b.call('bar')
[4] pry(main)* end  
=> :greeting

Proc オブジェクト

Proc クラスのインスタンス (Proc オブジェクト) を作成する場合は, 以下のように Proc.new にブロックを渡す.

p = Proc.new do
  'Hello'
end
p = Proc.new { 'Hello' }

Proc オブジェクトの実行は call メソッドを利用する.

[5] pry(main)> p = Proc.new { 'Hello' }
=> #<Proc:0x00005590101b2330@(pry):11>
[6] pry(main)> p.call
=> "Hello"

引数を利用する Proc オブジェクトは以下のように定義する.

p = Proc.new { |a, b| a + b }
p.call(10, 20)

以下, 実行結果.

[7] pry(main)> p = Proc.new { |a, b| a + b }
=> #<Proc:0x000055900fa664a0@(pry):13>
[8] pry(main)> p.call(10, 20)
=> 30

引数にはデフォルト値, 可変長引数, キーワード引数等, 通常のメソッドのように引数を受け取ることが出来る.

Proc オブジェクトをブロックの代わりに渡す

  • Proc オブジェクトもブロックと同様に「処理のかたまり」
  • ブロックと異なり, オブジェクトとして扱うことが出来る
[1] pry(main)> def greeting(&block)
[1] pry(main)*   p block.class  
[1] pry(main)*   block.call('foo')  
[1] pry(main)* end  
=> :greeting
[2] pry(main)> greeting do |text|
[2] pry(main)*   puts text
[2] pry(main)* end  
Proc
foo
=> nil
[1] pry(main)> def greeting(p)
[1] pry(main)*   puts 'foo'  
[1] pry(main)*   puts p.call('bar')  
[1] pry(main)* end  
=> :greeting
[2] pry(main)> 
[3] pry(main)> p = Proc.new { |text| text * 2 }
=> #<Proc:0x000055a568339a10@(pry):5>
[4] pry(main)> greeting(p)
foo
barbar
=> nil
  • ブロックの代わりに Proc オブジェクトをメソッドの引数として渡すことも出来る
    • メソッドが受け取れるブロックは最大 1 個だが...
    • Proc オブジェクトはただのオブジェクトになるので, 引数の個数として制限が無い

ふむふむ.

クロージャ

  • メソッドで生成されたコンテキストを保持しているメソッド = クロージャ
  • Proc オブジェクト内で各コンテキストを参照すると, メソッドの実行後も Proc オブジェクトはそのコンテキストにアクセスし続けることが出来る
irb(main):001:0> n = 0
=> 0
irb(main):002:0> p = Proc.new do
irb(main):003:1* n = n + 1
irb(main):004:1> end
=> #<Proc:0x0000564a45143a58@(irb):2>
irb(main):005:0> p.call
=> 1
irb(main):006:0> p.call
=> 2
irb(main):007:0> p.call
=> 3

ふむふむ.