How can I pass a method as an argument in Ruby? - ruby

I am passing a method as an argument to a called function:
def my_function(args1)
puts args1
end
def my_calling_method
self.my_function(def do_this
return 2*3
end)
end
When I call my_calling_method which makes a call to my_function, I am getting args1 as nil instead of def do_this return 2*3 end.
Am I doing anything wrong? Can we pass method as an argument in Ruby?
Alright, I tried implemented a Proc for my requirement now but I am having a hard time to pass it to the calling method.
my_Proc = Proc.new do
return 2*3
end
def my_calling_method
self.my_function
end
def my_function my_Proc
my_Proc.call
end
The reference material I used passes a Proc as an argument to the method like I do, but I am getting error, zero arguments passed to my_function as I am not passing any argument through my_calling_method.

Defining a new method will not return a value. (Much like writing down a phone number does not result in a conversation.)
irb:001>def something
irb:002> # code here
irb:003>end
=> nil
When you run that in IRB, you get nil, right? So, if you define that method as part of a method call:
some_method( def something; stuff; end )
You are getting back nil from the method definition and hence nil is what gets passed into some_method.
Without knowing exactly what it is you are trying to accomplish, I will tell you that you can pass methods, or what are called "blocks", into your method call.
def my_function(&block)
puts block.call
end
my_function {2*3}
#=> 6
my_function {t = Time.now; t + 8640}
#=> 2013-08-09 14:03:29 -0500
my_function do
name = "Charlie"
name.downcase.reverse.capitalize
end
#=> Eilrahc
In fact, this is what you are doing (more or less) with the method .each
array.each {|ele| foo}
I recommend reading up on Ruby's block, Procs, and Lambdas for passing methods in as arguments.

Nothing wrong. A method definition returns nil. The value of def do_this; return 2*3 end is nil. That is what you get.

Related

How are these objects different? [duplicate]

And when would you use one rather than the other?
One difference is in the way they handle arguments. Creating a proc using proc {} and Proc.new {} are equivalent. However, using lambda {} gives you a proc that checks the number of arguments passed to it. From ri Kernel#lambda:
Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.
An example:
p = Proc.new {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28#(irb):1>
p.call 1, 2 # => 5
p.call 1 # => NoMethodError: undefined method `**' for nil:NilClass
p.call 1, 2, 3 # => 5
l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c#(irb):5 (lambda)>
l.call 1, 2 # => 5
l.call 1 # => ArgumentError: wrong number of arguments (1 for 2)
l.call 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2)
In addition, as Ken points out, using return inside a lambda returns the value of that lambda, but using return in a proc returns from the enclosing block.
lambda { return :foo }.call # => :foo
return # => LocalJumpError: unexpected return
Proc.new { return :foo }.call # => LocalJumpError: unexpected return
So for most quick uses they're the same, but if you want automatic strict argument checking (which can also sometimes help with debugging), or if you need to use the return statement to return the value of the proc, use lambda.
The real difference between procs and lambdas has everything to do with control flow keywords. I am talking about return, raise, break, redo, retry etc. – those control words. Let's say you have a return statement in a proc. When you call your proc, it will not only dump you out of it, but will also return from the enclosing method e.g.:
def my_method
puts "before proc"
my_proc = Proc.new do
puts "inside proc"
return
end
my_proc.call
puts "after proc"
end
my_method
shoaib#shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
The final puts in the method, was never executed, since when we called our proc, the return within it dumped us out of the method. If, however, we convert our proc to a lambda, we get the following:
def my_method
puts "before proc"
my_proc = lambda do
puts "inside proc"
return
end
my_proc.call
puts "after proc"
end
my_method
shoaib#shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
after proc
The return within the lambda only dumps us out of the lambda itself and the enclosing method continues executing. The way control flow keywords are treated within procs and lambdas is the main difference between them
There are only two main differences.
First, a lambda checks the number of arguments passed to it, while a proc does not. This means that a lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.
Second, when a lambda returns, it passes control back to the calling method; when a proc returns, it does so immediately, without going back to the calling method.
To see how this works, take a look at the code below. Our first method calls a proc; the second calls a lambda.
def batman_ironman_proc
victor = Proc.new { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_proc # prints "Batman will win!"
def batman_ironman_lambda
victor = lambda { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_lambda # prints "Iron Man will win!"
See how the proc says "Batman will win!", this is because it returns immediately, without going back to the batman_ironman_proc method.
Our lambda, however, goes back into the method after being called, so the method returns the last code it evaluates: "Iron Man will win!"
# Proc Examples
p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p) # The '&' tells ruby to turn the proc into a block
proc = Proc.new { puts "Hello World" }
proc.call
# Lambda Examples
lam = lambda { |x| puts x*2 }
[1,2,3].each(&lam)
lam = lambda { puts "Hello World" }
lam.call
Differences between Procs and Lambdas
Before I get into the differences between procs and lambdas, it is important to mention that they are both Proc objects.
proc = Proc.new { puts "Hello world" }
lam = lambda { puts "Hello World" }
proc.class # returns 'Proc'
lam.class # returns 'Proc'
However, lambdas are a different ‘flavor’ of procs. This slight difference is shown when returning the objects.
proc # returns '#<Proc:0x007f96b1032d30#(irb):75>'
lam # returns '<Proc:0x007f96b1b41938#(irb):76 (lambda)>'
1. Lambdas check the number of arguments, while procs do not
lam = lambda { |x| puts x } # creates a lambda that takes 1 argument
lam.call(2) # prints out 2
lam.call # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3) # ArgumentError: wrong number of arguments (3 for 1)
In contrast, procs don’t care if they are passed the wrong number of arguments.
proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument
proc.call(2) # prints out 2
proc.call # returns nil
proc.call(1,2,3) # prints out 1 and forgets about the extra arguments
2. Lambdas and procs treat the ‘return’ keyword differently
‘return’ inside of a lambda triggers the code right outside of the lambda code
def lambda_test
lam = lambda { return }
lam.call
puts "Hello world"
end
lambda_test # calling lambda_test prints 'Hello World'
‘return’ inside of a proc triggers the code outside of the method where the proc is being executed
def proc_test
proc = Proc.new { return }
proc.call
puts "Hello world"
end
proc_test # calling proc_test prints nothing
And to answer your other query, which one to use and when ? I'll follow #jtbandes as he has mentioned
So for most quick uses they're the same, but if you want automatic
strict argument checking (which can also sometimes help with
debugging), or if you need to use the return statement to return the
value of the proc, use lambda.
Originally posted here
Generally speaking, lambdas are more intuitive than procs because they’re
more similar to methods. They’re pretty strict about arity, and they simply
exit when you call return . For this reason, many Rubyists use lambdas as a
first choice, unless they need the specific features of procs.
Procs: Objects of class Proc . Like blocks, they are evaluated in the scope
where they’re defined.
Lambdas: Also objects of class Proc but subtly different from regular procs.
They’re closures like blocks and procs, and as such they’re evaluated in
the scope where they’re defined.
Creating Proc
a = Proc.new { |x| x 2 }
Creating lambda
b = lambda { |x| x 2 }
Here is another way to understand this.
A block is a chunk of code attached to the invocation to a call of a method on an object. In the below example, self is an instance of an anonymous class inheriting from ActionView::Base in the Rails framework (which itself includes many helper modules). card is a method we call on self. We pass in an argument to the method and then we always attach the block to the end of the method invocation:
self.card :contacts do |c|
// a chunk of valid ruby code
end
Ok, so we are passing a chunk of code to a method. But how do we make use of this block? One option is to convert the chunk of code into an object. Ruby offers three ways to convert a chunk of code into an object
# lambda
> l = lambda { |a| a + 1 }
> l.call(1)
=> 2
# Proc.new
> l2= Proc.new { |a| a + 1 }
> l2.call(1)
=> 2
# & as the last method argument with a local variable name
def add(&block)
end
In the method above, the & converts the block passed to the method into an object and stores that object in the local variable block. In fact, we can show that it has the same behavior as lambda and Proc.new:
def add(&block)
block
end
l3 = add { |a| a + 1 }
l3.call(1)
=> 2
This is IMPORTANT. When you pass a block to a method and convert it using &, the object it creates uses Proc.new to do the conversion.
Note that I avoided the use of "proc" as an option. That's because it Ruby 1.8, it is the same as lambda and in Ruby 1.9, it is the same as Proc.new and in all Ruby versions it should be avoided.
So then you ask what is the difference between lambda and Proc.new?
First, in terms of parameter passing, lambda behaves like a method call. It will raise an exception if you pass the wrong number of arguments. In contrast, Proc.new behaves like parallel assignment. All unused arguments get converted into nil:
> l = lambda {|a,b| puts "#{a} + #{b}" }
=> #<Proc:0x007fbffcb47e40#(irb):19 (lambda)>
> l.call(1)
ArgumentError: wrong number of arguments (1 for 2)
> l2 = Proc.new {|a,b| puts "#{a} + #{b}" }
=> #<Proc:0x007fbffcb261a0#(irb):21>
> l2.call(1)
1 +
Second, lambda and Proc.new handle the return keyword differently. When you do a return inside of Proc.new, it actually returns from the enclosing method, that is, the surrounding context. When you return from a lambda block, it just returns from the block, not the enclosing method. Basically, it exits from the call to the block and continues execution with the rest of the enclosing method.
> def add(a,b)
l = Proc.new { return a + b}
l.call
puts "now exiting method"
end
> add(1,1)
=> 2 # NOTICE it never prints the message "now exiting method"
> def add(a,b)
l = lambda { return a + b }
l.call
puts "now exiting method"
end
> add(1,1)
=> now exiting method # NOTICE this time it prints the message "now exiting method"
So why this behavioral difference? The reason is because with Proc.new, we can use iterators inside the context of enclosing methods and draw logical conclusions. Look at this example:
> def print(max)
[1,2,3,4,5].each do |val|
puts val
return if val > max
end
end
> print(3)
1
2
3
4
We expect that when we invoke return inside the iterator, it will return from the enclosing method. Remember the blocks passed to iterators get converted to objects using Proc.new and that is why when we use return, it will exit the enclosing method.
You can think of lambdas as anonymous methods, they isolate individual blocks of code into an object that can be treated like a method. Ultimately, think of a lambda as behaving as an anomyous method and Proc.new behaving as inline code.
A helpful post on ruby guides: blocks, procs & lambdas
Procs return from the current method, while lambdas return from the lambda itself.
Procs don’t care about the correct number of arguments, while lambdas will raise an exception.
the differences between proc and lambda is that proc is just a copy of code with arguments replaced in turn, while lambda is a function like in other languages. (behavior of return, arguments checks)

proc return vs lambda return

Why is Proc in ruby return before executing remaining codes in a method from which Proc was called?
def hello
a = Proc.new{ return }
a.call
puts "Hello"
end
def proc
hello
puts "Proc"
end
Here return will skip puts "Hello" and prints only puts "Proc"
But lambda prints puts "Hello" as well.
What's the reason for this?
You should see comment in this answer https://stackoverflow.com/a/723/4576274.
It states
A lambda is an anonymous method. Since it's a method, it returns a
value, and the method that called it can do with it whatever it wants,
including ignoring it and returning a different value.
A Proc is like
pasting in a code snippet. It doesn't act like a method. So when a
return happens within the Proc, that's just part of the code of the
method that called it

Ruby: convert proc to lambda?

Is it possible to convert a proc-flavored Proc into a lambda-flavored Proc?
Bit surprised that this doesn't work, at least in 1.9.2:
my_proc = proc {|x| x}
my_lambda = lambda &p
my_lambda.lambda? # => false!
This one was a bit tricky to track down. Looking at the docs for Proc#lambda? for 1.9, there's a fairly lengthy discussion about the difference between procs and lamdbas.
What it comes down to is that a lambda enforces the correct number of arguments, and a proc doesn't. And from that documentation, about the only way to convert a proc into a lambda is shown in this example:
define_method always defines a method without the tricks, even if a non-lambda Proc object is given. This is the only exception which the tricks are not preserved.
class C
define_method(:e, &proc {})
end
C.new.e(1,2) => ArgumentError
C.new.method(:e).to_proc.lambda? => true
If you want to avoid polluting any class, you can just define a singleton method on an anonymous object in order to coerce a proc to a lambda:
def convert_to_lambda &block
obj = Object.new
obj.define_singleton_method(:_, &block)
return obj.method(:_).to_proc
end
p = Proc.new {}
puts p.lambda? # false
puts(convert_to_lambda(&p).lambda?) # true
puts(convert_to_lambda(&(lambda {})).lambda?) # true
It is not possible to convert a proc to a lambda without trouble. The answer by Mark Rushakoff doesn't preserve the value of self in the block, because self becomes Object.new. The answer by Pawel Tomulik can't work with Ruby 2.1, because define_singleton_method now returns a Symbol, so to_lambda2 returns :_.to_proc.
My answer is also wrong:
def convert_to_lambda &block
obj = block.binding.eval('self')
Module.new.module_exec do
define_method(:_, &block)
instance_method(:_).bind(obj).to_proc
end
end
It preserves the value of self in the block:
p = 42.instance_exec { proc { self }}
puts p.lambda? # false
puts p.call # 42
q = convert_to_lambda &p
puts q.lambda? # true
puts q.call # 42
But it fails with instance_exec:
puts 66.instance_exec &p # 66
puts 66.instance_exec &q # 42, should be 66
I must use block.binding.eval('self') to find the correct object. I put my method in an anonymous module, so it never pollutes any class. Then I bind my method to the correct object. This works though the object never included the module! The bound method makes a lambda.
66.instance_exec &q fails because q is secretly a method bound to 42, and instance_exec can't rebind the method. One might fix this by extending q to expose the unbound method, and redefining instance_exec to bind the unbound method to a different object. Even so, module_exec and class_exec would still fail.
class Array
$p = proc { def greet; puts "Hi!"; end }
end
$q = convert_to_lambda &$p
Hash.class_exec &$q
{}.greet # undefined method `greet' for {}:Hash (NoMethodError)
The problem is that Hash.class_exec &$q defines Array#greet and not Hash#greet. (Though $q is secretly a method of an anonymous module, it still defines methods in Array, not in the anonymous module.) With the original proc, Hash.class_exec &$p would define Hash#greet. I conclude that convert_to_lambda is wrong because it doesn't work with class_exec.
Here is possible solution:
class Proc
def to_lambda
return self if lambda?
# Save local reference to self so we can use it in module_exec/lambda scopes
source_proc = self
# Convert proc to unbound method
unbound_method = Module.new.module_exec do
instance_method( define_method( :_proc_call, &source_proc ))
end
# Return lambda which binds our unbound method to correct receiver and calls it with given args/block
lambda do |*args, &block|
# If binding doesn't changed (eg. lambda_obj.call) then bind method to original proc binding,
# otherwise bind to current binding (eg. instance_exec(&lambda_obj)).
unbound_method.bind( self == source_proc ? source_proc.receiver : self ).call( *args, &block )
end
end
def receiver
binding.eval( "self" )
end
end
p1 = Proc.new { puts "self = #{self.inspect}" }
l1 = p1.to_lambda
p1.call #=> self = main
l1.call #=> self = main
p1.call( 42 ) #=> self = main
l1.call( 42 ) #=> ArgumentError: wrong number of arguments (1 for 0)
42.instance_exec( &p1 ) #=> self = 42
42.instance_exec( &l1 ) #=> self = 42
p2 = Proc.new { return "foo" }
l2 = p2.to_lambda
p2.call #=> LocalJumpError: unexpected return
l2.call #=> "foo"
Should work on Ruby 2.1+
Cross ruby compatiable library for converting procs to lambdas:
https://github.com/schneems/proc_to_lambda
The Gem:
http://rubygems.org/gems/proc_to_lambda
The above code doesn't play nicely with instance_exec but I think there is simple fix for that. Here I have an example which illustrates the issue and solution:
# /tmp/test.rb
def to_lambda1(&block)
obj = Object.new
obj.define_singleton_method(:_,&block)
obj.method(:_).to_proc
end
def to_lambda2(&block)
Object.new.define_singleton_method(:_,&block).to_proc
end
l1 = to_lambda1 do
print "to_lambda1: #{self.class.name}\n"
end
print "l1.lambda?: #{l1.lambda?}\n"
l2 = to_lambda2 do
print "to_lambda2: #{self.class.name}\n"
end
print "l2.lambda?: #{l2.lambda?}\n"
class A; end
A.new.instance_exec &l1
A.new.instance_exec &l2
to_lambda1 is basically the implementation proposed by Mark, to_lambda2 is a "fixed" code.
The output from above script is:
l1.lambda?: true
l2.lambda?: true
to_lambda1: Object
to_lambda2: A
In fact I'd expect instance_exec to output A, not Object (instance_exec should change binding). I don't know why this work differently, but I suppose that define_singleton_method returns a method that is not yet bound to Object and Object#method returns an already bound method.

What's the difference between a proc and a lambda in Ruby?

And when would you use one rather than the other?
One difference is in the way they handle arguments. Creating a proc using proc {} and Proc.new {} are equivalent. However, using lambda {} gives you a proc that checks the number of arguments passed to it. From ri Kernel#lambda:
Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.
An example:
p = Proc.new {|a, b| puts a**2+b**2 } # => #<Proc:0x3c7d28#(irb):1>
p.call 1, 2 # => 5
p.call 1 # => NoMethodError: undefined method `**' for nil:NilClass
p.call 1, 2, 3 # => 5
l = lambda {|a, b| puts a**2+b**2 } # => #<Proc:0x15016c#(irb):5 (lambda)>
l.call 1, 2 # => 5
l.call 1 # => ArgumentError: wrong number of arguments (1 for 2)
l.call 1, 2, 3 # => ArgumentError: wrong number of arguments (3 for 2)
In addition, as Ken points out, using return inside a lambda returns the value of that lambda, but using return in a proc returns from the enclosing block.
lambda { return :foo }.call # => :foo
return # => LocalJumpError: unexpected return
Proc.new { return :foo }.call # => LocalJumpError: unexpected return
So for most quick uses they're the same, but if you want automatic strict argument checking (which can also sometimes help with debugging), or if you need to use the return statement to return the value of the proc, use lambda.
The real difference between procs and lambdas has everything to do with control flow keywords. I am talking about return, raise, break, redo, retry etc. – those control words. Let's say you have a return statement in a proc. When you call your proc, it will not only dump you out of it, but will also return from the enclosing method e.g.:
def my_method
puts "before proc"
my_proc = Proc.new do
puts "inside proc"
return
end
my_proc.call
puts "after proc"
end
my_method
shoaib#shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
The final puts in the method, was never executed, since when we called our proc, the return within it dumped us out of the method. If, however, we convert our proc to a lambda, we get the following:
def my_method
puts "before proc"
my_proc = lambda do
puts "inside proc"
return
end
my_proc.call
puts "after proc"
end
my_method
shoaib#shoaib-ubuntu-vm:~/tmp$ ruby a.rb
before proc
inside proc
after proc
The return within the lambda only dumps us out of the lambda itself and the enclosing method continues executing. The way control flow keywords are treated within procs and lambdas is the main difference between them
There are only two main differences.
First, a lambda checks the number of arguments passed to it, while a proc does not. This means that a lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.
Second, when a lambda returns, it passes control back to the calling method; when a proc returns, it does so immediately, without going back to the calling method.
To see how this works, take a look at the code below. Our first method calls a proc; the second calls a lambda.
def batman_ironman_proc
victor = Proc.new { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_proc # prints "Batman will win!"
def batman_ironman_lambda
victor = lambda { return "Batman will win!" }
victor.call
"Iron Man will win!"
end
puts batman_ironman_lambda # prints "Iron Man will win!"
See how the proc says "Batman will win!", this is because it returns immediately, without going back to the batman_ironman_proc method.
Our lambda, however, goes back into the method after being called, so the method returns the last code it evaluates: "Iron Man will win!"
# Proc Examples
p = Proc.new { |x| puts x*2 }
[1,2,3].each(&p) # The '&' tells ruby to turn the proc into a block
proc = Proc.new { puts "Hello World" }
proc.call
# Lambda Examples
lam = lambda { |x| puts x*2 }
[1,2,3].each(&lam)
lam = lambda { puts "Hello World" }
lam.call
Differences between Procs and Lambdas
Before I get into the differences between procs and lambdas, it is important to mention that they are both Proc objects.
proc = Proc.new { puts "Hello world" }
lam = lambda { puts "Hello World" }
proc.class # returns 'Proc'
lam.class # returns 'Proc'
However, lambdas are a different ‘flavor’ of procs. This slight difference is shown when returning the objects.
proc # returns '#<Proc:0x007f96b1032d30#(irb):75>'
lam # returns '<Proc:0x007f96b1b41938#(irb):76 (lambda)>'
1. Lambdas check the number of arguments, while procs do not
lam = lambda { |x| puts x } # creates a lambda that takes 1 argument
lam.call(2) # prints out 2
lam.call # ArgumentError: wrong number of arguments (0 for 1)
lam.call(1,2,3) # ArgumentError: wrong number of arguments (3 for 1)
In contrast, procs don’t care if they are passed the wrong number of arguments.
proc = Proc.new { |x| puts x } # creates a proc that takes 1 argument
proc.call(2) # prints out 2
proc.call # returns nil
proc.call(1,2,3) # prints out 1 and forgets about the extra arguments
2. Lambdas and procs treat the ‘return’ keyword differently
‘return’ inside of a lambda triggers the code right outside of the lambda code
def lambda_test
lam = lambda { return }
lam.call
puts "Hello world"
end
lambda_test # calling lambda_test prints 'Hello World'
‘return’ inside of a proc triggers the code outside of the method where the proc is being executed
def proc_test
proc = Proc.new { return }
proc.call
puts "Hello world"
end
proc_test # calling proc_test prints nothing
And to answer your other query, which one to use and when ? I'll follow #jtbandes as he has mentioned
So for most quick uses they're the same, but if you want automatic
strict argument checking (which can also sometimes help with
debugging), or if you need to use the return statement to return the
value of the proc, use lambda.
Originally posted here
Generally speaking, lambdas are more intuitive than procs because they’re
more similar to methods. They’re pretty strict about arity, and they simply
exit when you call return . For this reason, many Rubyists use lambdas as a
first choice, unless they need the specific features of procs.
Procs: Objects of class Proc . Like blocks, they are evaluated in the scope
where they’re defined.
Lambdas: Also objects of class Proc but subtly different from regular procs.
They’re closures like blocks and procs, and as such they’re evaluated in
the scope where they’re defined.
Creating Proc
a = Proc.new { |x| x 2 }
Creating lambda
b = lambda { |x| x 2 }
Here is another way to understand this.
A block is a chunk of code attached to the invocation to a call of a method on an object. In the below example, self is an instance of an anonymous class inheriting from ActionView::Base in the Rails framework (which itself includes many helper modules). card is a method we call on self. We pass in an argument to the method and then we always attach the block to the end of the method invocation:
self.card :contacts do |c|
// a chunk of valid ruby code
end
Ok, so we are passing a chunk of code to a method. But how do we make use of this block? One option is to convert the chunk of code into an object. Ruby offers three ways to convert a chunk of code into an object
# lambda
> l = lambda { |a| a + 1 }
> l.call(1)
=> 2
# Proc.new
> l2= Proc.new { |a| a + 1 }
> l2.call(1)
=> 2
# & as the last method argument with a local variable name
def add(&block)
end
In the method above, the & converts the block passed to the method into an object and stores that object in the local variable block. In fact, we can show that it has the same behavior as lambda and Proc.new:
def add(&block)
block
end
l3 = add { |a| a + 1 }
l3.call(1)
=> 2
This is IMPORTANT. When you pass a block to a method and convert it using &, the object it creates uses Proc.new to do the conversion.
Note that I avoided the use of "proc" as an option. That's because it Ruby 1.8, it is the same as lambda and in Ruby 1.9, it is the same as Proc.new and in all Ruby versions it should be avoided.
So then you ask what is the difference between lambda and Proc.new?
First, in terms of parameter passing, lambda behaves like a method call. It will raise an exception if you pass the wrong number of arguments. In contrast, Proc.new behaves like parallel assignment. All unused arguments get converted into nil:
> l = lambda {|a,b| puts "#{a} + #{b}" }
=> #<Proc:0x007fbffcb47e40#(irb):19 (lambda)>
> l.call(1)
ArgumentError: wrong number of arguments (1 for 2)
> l2 = Proc.new {|a,b| puts "#{a} + #{b}" }
=> #<Proc:0x007fbffcb261a0#(irb):21>
> l2.call(1)
1 +
Second, lambda and Proc.new handle the return keyword differently. When you do a return inside of Proc.new, it actually returns from the enclosing method, that is, the surrounding context. When you return from a lambda block, it just returns from the block, not the enclosing method. Basically, it exits from the call to the block and continues execution with the rest of the enclosing method.
> def add(a,b)
l = Proc.new { return a + b}
l.call
puts "now exiting method"
end
> add(1,1)
=> 2 # NOTICE it never prints the message "now exiting method"
> def add(a,b)
l = lambda { return a + b }
l.call
puts "now exiting method"
end
> add(1,1)
=> now exiting method # NOTICE this time it prints the message "now exiting method"
So why this behavioral difference? The reason is because with Proc.new, we can use iterators inside the context of enclosing methods and draw logical conclusions. Look at this example:
> def print(max)
[1,2,3,4,5].each do |val|
puts val
return if val > max
end
end
> print(3)
1
2
3
4
We expect that when we invoke return inside the iterator, it will return from the enclosing method. Remember the blocks passed to iterators get converted to objects using Proc.new and that is why when we use return, it will exit the enclosing method.
You can think of lambdas as anonymous methods, they isolate individual blocks of code into an object that can be treated like a method. Ultimately, think of a lambda as behaving as an anomyous method and Proc.new behaving as inline code.
A helpful post on ruby guides: blocks, procs & lambdas
Procs return from the current method, while lambdas return from the lambda itself.
Procs don’t care about the correct number of arguments, while lambdas will raise an exception.
the differences between proc and lambda is that proc is just a copy of code with arguments replaced in turn, while lambda is a function like in other languages. (behavior of return, arguments checks)

Difference between block and &block in Ruby

Why sometimes I should use block and other times &block inside functions that accept blocks?
block is just a local variable, &block is a reference to the block passed to the method.
def foo(block = nil)
p block
end
foo # => nil
foo("test") # => test
foo { puts "this block will not be called" } # => nil
def foo(&block)
p block
end
foo # => nil
foo("test") # => ArgumentError: wrong number of arguments (1 for 0)
foo { puts "This block won't get called, but you'll se it referenced as a proc." }
# => #<Proc:0x0000000100124ea8#untitled:20>
You can also use &block when calling methods to pass a proc as a block to a method, so that you can use procs just as you use blocks.
my_proc = proc {|i| i.upcase }
p ["foo", "bar", "baz"].map(&my_proc)
# => ["FOO", "BAR", "BAZ"]
p ["foo", "bar", "baz"].map(my_proc)
# => ArgumentError: wrong number of arguments (1 for 0)
The variable name block doesn't mean anything special. You can use &strawberries if you like, the ampersand is the key here.
You might find this article helpful.
In an argument list, &whatever takes the block that was passed to the method and wraps it in a Proc object. The Proc is stored in a variable called whatever (where that can be whatever name you typed after the ampersand, of course — usually it's "block"). After a method call, the &whatever syntax turns a Proc into a block. So if you define a method like so:
def thing(&block)
thing2 &block
end
You're defining a method that takes a block and then calls another method with that block.
If you don't set the & before block, Ruby won't recognize it's relationship to the "block" you pass to the function. Here some examples.
def f(x, block); end
f(3) { 2+2 } # gives an error, because "block" is a
# regular second argument (which is missing)
def g(x, &block); end
g(3) { 2+2 } # legal
def h(x); end
h(3) { 2+2 } # legal
For later use in a function:
def x(&block) # x is a 0 param function
y(block) # y is a 1 param function (taking one "Proc")
z(&block) # z is a 0 param function (like x) with the block x received
end
So, if you call z(&block) it's (nearly!!) the same as calling z { yield }: You just pass the block to the next function.

Resources