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)
Related
The implicit block argument passed to a Ruby method can be executed using yield, or its existence can be checked using block_given?. I'm trying to procify this implicit block to pass it to another method.
Is this possible?
(It's access to the implicit block argument I'm asking about. Replacing this with an explicit argument won't cut it.)
You can procify it, and more importantly give it a name so you can reference it, using the & ampersand unary prefix sigil in the parameter list of the method, like so:
#implicit, anonymous, cannot be referenced:
def foo
yield 23 if block_given?
end
foo {|i| puts i }
# 23
#explicit, named, can be referenced:
def bar(&blk)
yield 23 if block_given? # still works
blk.(42) if blk # but now it also has a name and is a `Proc`
# since we have the block available as an object, we can inspect it
p blk.arity, blk.parameters, blk.source_location, blk.binding
b = blk.binding
p b.local_variables.map {|var| [var, b.local_variable_get(var)] }.to_h
end
quux = "Hello"
bar { |a, b, c = nil, d: nil, &e| puts a }
# 23
# 42
# 2
# [[:opt, :a], [:opt, :b], [:opt, :c], [:key, :d], [:block, :e]]
# ["(irb)", 24]
# #<Binding:0x00007fb091051308>
# { :quux => "Hello" }
Those are your two choices:
implicit, anonymous, not an object
explicit, named, Proc
There used to be an undocumented trick that was actually an unintended side-effect of how Proc::new was implemented in MRI: Proc::new did not check whether you passed a block or not, it simply assumed that you passed a block and would take the first block off the top of the internal VM stack. So, if you didn't pass a block to Proc::new, it would actually end up creating a Proc for the implicit block that was passed to the method (since that was the one which just happened to be on the top of the stack).
But, that was never portable, never guaranteed, never worked in all Ruby implementations, and AFAIK no longer works in YARV.
You can refer to the block argument via Proc.new. From the docs:
::new may be called without a block only within a method with an attached block, in which case that block is converted to the Proc object.
Example:
def bar
yield * 2
end
def foo
bar(&Proc.new)
end
foo(123)
#=> 456
Note that Proc.new raises an ArgumentError when called without passing a block.
Take a look at this answer. In your case it would be something like:
def outer
wrapper = lambda { |something|
p 'Do something crazy in this wrapper'
yield(something)
}
other_method(&wrapper)
end
def other_method
yield(5)
end
outer { |x| puts x + 3 }
With that you get:
"Do something crazy in this wrapper"
8
=> nil
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
I am trying to understand blocks and yield and how they work in Ruby.
How is yield used? Many of the Rails applications I've looked at use yield in a weird way.
Can someone explain to me or show me where to go to understand them?
Yes, it is a bit puzzling at first.
In Ruby, methods can receive a code block in order to perform arbitrary segments of code.
When a method expects a block, you can invoke it by calling the yield function.
Example:
Take Person, a class with a name attribute and a do_with_name method. When the method is invoked it will pass the name attribute to the block.
class Person
def initialize( name )
#name = name
end
def do_with_name # expects a block
yield( #name ) # invoke the block and pass the `#name` attribute
end
end
Now you can invoke this method and pass an arbitrary code block.
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
Would print:
Got: Oscar
Notice the block receives as a parameter a variable called value. When the code invokes yield it passes as argument the value of #name.
yield( #name )
The same method can be invoked with a different block.
For instance to reverse the name:
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
=> "racsO"
Other more interesting real life examples:
Filter elements in an array:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
=> ["Tuesday", "Thursday"]
Or sort by name length:
days.sort do |x,y|
x.size <=> y.size
end
=> ["Monday", "Friday", "Tuesday", "Thursday", "Wednesday"]
If the block is optional you can use:
yield(value) if block_given?
If is not optional, just invoke it.
You can try these examples on your computer with irb (Interactive Ruby Shell)
Here are all the examples in a copy/paste ready form:
class Person
def initialize( name )
#name = name
end
def do_with_name # expects a block
yield( #name ) # invoke the block and pass the `#name` attribute
end
end
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
# Filter elements in an array:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
# Sort by name length:
days.sort do |x,y|
x.size <=> y.size
end
In Ruby, methods can check to see if they were called in such a way that a block was provided in addition to the normal arguments. Typically this is done using the block_given? method but you can also refer to the block as an explicit Proc by prefixing an ampersand (&) before the final argument name.
If a method is invoked with a block then the method can yield control to the block (call the block) with some arguments, if needed. Consider this example method that demonstrates:
def foo(x)
puts "OK: called as foo(#{x.inspect})"
yield("A gift from foo!") if block_given?
end
foo(10)
# OK: called as foo(10)
foo(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as foo(123)
# BLOCK: A gift from foo! How nice =)
Or, using the special block argument syntax:
def bar(x, &block)
puts "OK: called as bar(#{x.inspect})"
block.call("A gift from bar!") if block
end
bar(10)
# OK: called as bar(10)
bar(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as bar(123)
# BLOCK: A gift from bar! How nice =)
It's quite possible that someone will provide a truly detailed answer here, but I've always found this post from Robert Sosinski to be a great explanation of the subtleties between blocks, procs & lambdas.
I should add that I believe the post I'm linking to is specific to ruby 1.8. Some things have changed in ruby 1.9, such as block variables being local to the block. In 1.8, you'd get something like the following:
>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Goodbye"
Whereas 1.9 would give you:
>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Hello"
I don't have 1.9 on this machine so the above might have an error in it.
I found this article to be very useful. In particular, the following example:
#!/usr/bin/ruby
def test
yield 5
puts "You are in the method test"
yield 100
end
test {|i| puts "You are in the block #{i}"}
test do |i|
puts "You are in the block #{i}"
end
which should give the following output:
You are in the block 5
You are in the method test
You are in the block 100
You are in the block 5
You are in the method test
You are in the block 100
So essentially each time a call is made to yield ruby will run the code in the do block or inside {}. If a parameter is provided to yield then this will be provided as a parameter to the do block.
For me, this was the first time that I understood really what the do blocks were doing. It is basically a way for the function to give access to internal data structures, be that for iteration or for configuration of the function.
So when in rails you write the following:
respond_to do |format|
format.html { render template: "my/view", layout: 'my_layout' }
end
This will run the respond_to function which yields the do block with the (internal) format parameter. You then call the .html function on this internal variable which in turn yields the code block to run the render command. Note that .html will only yield if it is the file format requested. (technicality: these functions actually use block.call not yield as you can see from the source but the functionality is essentially the same, see this question for a discussion.) This provides a way for the function to perform some initialisation then take input from the calling code and then carry on processing if required.
Or put another way, it's similar to a function taking an anonymous function as an argument and then calling it in javascript.
I wanted to sort of add why you would do things that way to the already great answers.
No idea what language you are coming from, but assuming it is a static language, this sort of thing will look familiar. This is how you read a file in java
public class FileInput {
public static void main(String[] args) {
File file = new File("C:\\MyFile.txt");
FileInputStream fis = null;
BufferedInputStream bis = null;
DataInputStream dis = null;
try {
fis = new FileInputStream(file);
// Here BufferedInputStream is added for fast reading.
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
// dis.available() returns 0 if the file does not have more lines.
while (dis.available() != 0) {
// this statement reads the line from the file and print it to
// the console.
System.out.println(dis.readLine());
}
// dispose all the resources after using them.
fis.close();
bis.close();
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ignoring the whole stream chaining thing, The idea is this
Initialize resource that needs to be cleaned up
use resource
make sure to clean it up
This is how you do it in ruby
File.open("readfile.rb", "r") do |infile|
while (line = infile.gets)
puts "#{counter}: #{line}"
counter = counter + 1
end
end
Wildly different. Breaking this one down
tell the File class how to initialize the resource
tell the file class what to do with it
laugh at the java guys who are still typing ;-)
Here, instead of handling step one and two, you basically delegate that off into another class. As you can see, that dramatically brings down the amount of code you have to write, which makes things easier to read, and reduces the chances of things like memory leaks, or file locks not getting cleared.
Now, its not like you can't do something similar in java, in fact, people have been doing it for decades now. It's called the Strategy pattern. The difference is that without blocks, for something simple like the file example, strategy becomes overkill due to the amount of classes and methods you need to write. With blocks, it is such a simple and elegant way of doing it, that it doesn't make any sense NOT to structure your code that way.
This isn't the only way blocks are used, but the others (like the Builder pattern, which you can see in the form_for api in rails) are similar enough that it should be obvious whats going on once you wrap your head around this. When you see blocks, its usually safe to assume that the method call is what you want to do, and the block is describing how you want to do it.
In Ruby, a block is basically a chunk of code that can be passed to and executed by any method. Blocks are always used with methods, which usually feed data to them (as arguments).
Blocks are widely used in Ruby gems (including Rails) and in well-written Ruby code. They are not objects, hence cannot be assigned to variables.
Basic Syntax
A block is a piece of code enclosed by { } or do..end. By convention, the curly brace syntax should be used for single-line blocks and the do..end syntax should be used for multi-line blocks.
{ # This is a single line block }
do
# This is a multi-line block
end
Any method can receive a block as an implicit argument. A block is executed by the yield statement within a method. The basic syntax is:
def meditate
print "Today we will practice zazen"
yield # This indicates the method is expecting a block
end
# We are passing a block as an argument to the meditate method
meditate { print " for 40 minutes." }
Output:
Today we will practice zazen for 40 minutes.
When the yield statement is reached, the meditate method yields control to the block, the code within the block is executed and control is returned to the method, which resumes execution immediately following the yield statement.
When a method contains a yield statement, it is expecting to receive a block at calling time. If a block is not provided, an exception will be thrown once the yield statement is reached. We can make the block optional and avoid an exception from being raised:
def meditate
puts "Today we will practice zazen."
yield if block_given?
end meditate
Output:
Today we will practice zazen.
It is not possible to pass multiple blocks to a method. Each method can receive only one block.
See more at: http://www.zenruby.info/2016/04/introduction-to-blocks-in-ruby.html
I sometimes use "yield" like this:
def add_to_http
"http://#{yield}"
end
puts add_to_http { "www.example.com" }
puts add_to_http { "www.victim.com"}
Yields, to put it simply, allow the method you create to take and call blocks. The yield keyword specifically is the spot where the 'stuff' in the block will be performed.
There are two points I want to make about yield here. First, while a lot of answers here talk about different ways to pass a block to a method which uses yield, let's also talk about the control flow. This is especially relevant since you can yield MULTIPLE times to a block. Let's take a look at an example:
class Fruit
attr_accessor :kinds
def initialize
#kinds = %w(orange apple pear banana)
end
def each
puts 'inside each'
3.times { yield (#kinds.tap {|kinds| puts "selecting from #{kinds}"} ).sample }
end
end
f = Fruit.new
f.each do |kind|
puts 'inside block'
end
=> inside each
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
=> selecting from ["orange", "apple", "pear", "banana"]
=> inside block
When the each method is invoked, it executes line by line. Now when we get to the 3.times block, this block will be invoked 3 times. Each time it invokes yield. That yield is linked to the block associated with the method that called the each method. It is important to notice that each time yield is invoked, it returns control back to the block of the each method in client code. Once the block is finished executing, it returns back to the 3.times block. And this happens 3 times. So that block in client code is invoked on 3 separate occasions since yield is explicitly called 3 separate times.
My second point is about enum_for and yield. enum_for instantiates the Enumerator class and this Enumerator object also responds to yield.
class Fruit
def initialize
#kinds = %w(orange apple)
end
def kinds
yield #kinds.shift
yield #kinds.shift
end
end
f = Fruit.new
enum = f.to_enum(:kinds)
enum.next
=> "orange"
enum.next
=> "apple"
So notice every time we invoke kinds with the external iterator, it will invoke yield only once. The next time we call it, it will invoke the next yield and so on.
There's an interesting tidbit with regards to enum_for. The documentation online states the following:
enum_for(method = :each, *args) → enum
Creates a new Enumerator which will enumerate by calling method on obj, passing args if any.
str = "xyz"
enum = str.enum_for(:each_byte)
enum.each { |b| puts b }
# => 120
# => 121
# => 122
If you do not specify a symbol as an argument to enum_for, ruby will hook the enumerator to the receiver's each method. Some classes do not have an each method, like the String class.
str = "I like fruit"
enum = str.to_enum
enum.next
=> NoMethodError: undefined method `each' for "I like fruit":String
Thus, in the case of some objects invoked with enum_for, you must be explicit as to what your enumerating method will be.
Yield can be used as nameless block to return a value in the method. Consider the following code:
Def Up(anarg)
yield(anarg)
end
You can create a method "Up" which is assigned one argument. You can now assign this argument to yield which will call and execute an associated block. You can assign the block after the parameter list.
Up("Here is a string"){|x| x.reverse!; puts(x)}
When the Up method calls yield, with an argument, it is passed to the block variable to process the request.
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)
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.