simanのブログ

ゆるふわプログラマー。競技プログラミングやってます。Ruby好き

ryudai.rb第2回まとめ(1) Procとlambda編

ryudai.rb第2回が無事に終わりました。
今回は4人と前回より参加者は減りましたが、発表の内容の質は上がっていたいました。

今回の発表者はatton君です。

atton君の発表資料
https://github.com/atton-/ryudairb_002

今回はProcとブロック、イテレータについての発表でした。

Procについては「処理をオブジェクトとして扱う」ことができます。
例えば

siman = Proc.new{
  puts "hello world"
}

siman.call
hello world

こんな感じでProc.newのブロック文の中身をそのままsimanという変数に入れて、それをcallすることでsimanの中にある「puts "hello world"」を呼び出すといった処理を行なっています。

処理をオブジェクト化する方法は他にもあって

siman = lambda {
  puts "hello world"
}

siman.call
hello world

だったり

siman = -> {
  puts "hello world"
}

siman.call
hello world

だったりできます。
ちなみに「lambda」と「->」は同じ意味なので気にしないで大丈夫です。

Procとlambdaの違いについては大きく分けて2つあり1つは
・return文の抜け方が違う

lambdaの場合はブロック文の中の処理から抜ける

def siman_lambda
  siman = lambda { 
    return 10
  }
  p siman.call
end

siman_lambda
10

この場合はlambdaのブロック文の中の処理からぬけるため、returnされる値である10がpメソッドによって表示されています。

Procの場合は「callを実行した場所からのreturnとなる」

def siman_proc
  siman = Proc.new {
    return 10
  }
  p siman.call
end

siman_proc

この場合は何も表示されない。なぜならProcでのreturnは「callされた場所からのreturn」になるのでsiman_procのreturnとして実行されるからである。なので

def siman_proc
  siman = Proc.new {
    return 10
  }
  siman.call 
end

p siman_proc
10

こんな風に書いてあげるとちゃんと表示してくれる。

これにハマるとろくなことが無い。解決法としては「returnを使わない」らしい。

2つ目の違いは
・引数の厳密差

Procとlambdaは両方共ブロック引数をとることができるのだが、Procは厳密に与えなくても実行できる。

def siman_proc
  siman = Proc.new {|first, second|
    puts "first argument is #{first}"
    puts "second argument is #{second}"
  }
  siman.call(1,2)
  siman.call(1)
end

siman_proc
first argument is 1
second argument is 2
first argument is 1
second argument is 

2回目のcallについては、2つ目の引数がないため何も表示されていないが実行はされている。

一方lambdaは引数の数があっていない場合はちゃんとエラーを出す。

def siman_lambda
  siman = lambda {|first, second|
    puts "first argument is #{first}"
    puts "second argument is #{second}"
  }
  siman.call(1,2)
  siman.call(1)
end

siman_lambda
first argument is 1
second argument is 2
lambda.rb:3:in `block in siman_lambda': wrong number of arguments (1 for 2) (ArgumentError)
	from lambda.rb:7:in `call'
	from lambda.rb:7:in `siman_lambda'
	from lambda.rb:10:in `<main>'

Procとlambdaの大きな違いはこんな感じ。

個人的にはlambdaの方が好きです。