ジョギング
- お昼休みに香椎浜 x 2 周
日課
- お休み
夕飯
- 鍋
- また, 出汁にこだわった
今日のるびぃ ~ yield と Proc (3) ~
引き続き, プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで の読書メモ.
Proc.new と lambda
Proc オブジェクトの生成方法.
Proc.new { |a, b| a + b } proc { |a, b| a + b }
以下, lambda メソッドを利用した生成方法.
# -> アロー演算子 ->(a, b) { a + b } lambda { |a, b| a + b }
以下, 実行例.
[1] pry(main)> p = Proc.new { |a, b| a + b } => #<Proc:0x000055628235c6d8@(pry):1> [2] pry(main)> p.class => Proc [3] pry(main)> p = proc { |a, b| a + b } => #<Proc:0x00005562822f3bd8@(pry):3> [4] pry(main)> p.class => Proc [5] pry(main)> p = ->(a, b) { a + b } => #<Proc:0x0000556282278780@(pry):5 (lambda)> [6] pry(main)> p.class => Proc [7] pry(main)> p = lambda { |a, b| a + b } => #<Proc:0x00005562821ec550@(pry):7 (lambda)> [8] pry(main)> p.class => Proc
Proc オブジェクトが Proc.new で作られたものなのか, lamda メソッドで作られたものなのかを判断したい場合には lambda? メソッドを利用する.
[1] pry(main)> p = proc { |a, b| a + b } => #<Proc:0x00005579e7146160@(pry):1> [2] pry(main)> p.lambda? => false [3] pry(main)> p = ->(a, b) { a + b } => #<Proc:0x00005579e708d430@(pry):3 (lambda)> [4] pry(main)> p.lambda? => true
何れも Proc オブジェクトを生成するが, 以下の点について挙動が異なる.
- 引数の扱い
- return と break の挙動
Proc.new と lambda ~ 引数の扱い ~
- Proc.new では引数の数に対して寛容
- lambda 式では引数の数に対して厳密
[1] pry(main)> p = Proc.new { |a, b| a.to_i + b.to_i } => #<Proc:0x0000560d3ee8acf0@(pry):1> [2] pry(main)> p.call(10, 20) => 30 [3] pry(main)> p.call(10) => 10 [4] pry(main)> p.call(10, 20, 100) => 30 [5] pry(main)> p = ->(a, b) { a.to_i + b.to_i } => #<Proc:0x0000560d3fa0c010@(pry):5 (lambda)> [6] pry(main)> p.call(10, 20) => 30 [7] pry(main)> p.call(10) ArgumentError: wrong number of arguments (given 1, expected 2) [8] pry(main)> p.call(10, 20, 100) ArgumentError: wrong number of arguments (given 3, expected 2)
Proc.new と lambda ~ return と break の挙動 ~
return の場合...
- Proc.new で生成した Proc オブジェクト内で return を呼ぶとメソッドそのものから抜ける
- lambda で生成した Proc オブジェクト内で return を呼ぶと lambda の処理から抜ける
[1] pry(main)> def func [1] pry(main)* p = Proc.new { return 1 } [1] pry(main)* p.call [1] pry(main)* 2 [1] pry(main)* end => :func [2] pry(main)> p func 1 => 1 [3] pry(main)> def func [3] pry(main)* p = -> {return 1} [3] pry(main)* p.call [3] pry(main)* 2 [3] pry(main)* end => :func [4] pry(main)> p func 2 => 2
break の場合...
- Proc.new で生成した Proc オブジェクト内で break を呼ぶと例外が発生する
- lambda で生成した Proc オブジェクト内で break を呼んだ場合, 例外は発生しないが map のループ処理は中断されず, 最後まで実行される
[1] pry(main)> def proc_func [1] pry(main)* p = Proc.new { |n| break n * 10 } [1] pry(main)* r = [1, 2, 3, 4, 5].map(&p) [1] pry(main)* end => :proc_func [2] pry(main)> [3] pry(main)> def lambda_func [3] pry(main)* p = ->(n) { break n * 10 } [3] pry(main)* r = [1, 2, 3, 4, 5].map(&p) [3] pry(main)* end => :lambda_func [4] pry(main)> p proc_func LocalJumpError: break from proc-closure [5] pry(main)> p lambda_func [10, 20, 30, 40, 50] => [10, 20, 30, 40, 50]
ふむふむ.