That's why I start with explaining the lambda and later compare with the Proc.
A simple lambda:
my_lambda = lambda { puts "A lambda" }
my_lambda.call
returns:
A lambdaSure, you can pass a parameter:
my_lambda = lambda { |param| puts "Parameter: #{param}" }
my_lambda.call(1)
returns:
Parameter: 1And yeah you can also pass more than one parameter like:
my_lambda = lambda { |p1, p2| puts "Parameters: #{p1}, #{p2}" }
my_lambda.call(1, 2)
returns:
Parameters: 1, 2You also can pass the lambda to a method for some reasons:
def my_function(block)
puts "before lambda"
block.call
puts "after lambda"
end
my_lambda = lambda { puts "inside lambda" }
my_function my_lambda
returns:
before lambda inside lambda after lambdaThough there are not many reasons for passing logic to an object method without using data of that object. You would more often want to "send logic" to an object for dynamically using its data. Then you pass a parameter like:
def my_function(block)
number = 0
block.call(number)
end
my_lambda = lambda { |p| puts "inside lambda: #{p += 1}" }
my_function my_lambda
returns:
inside lambda: 1At this point I note an essential property of closures. They automatically carry with them the bindings from the code location where they were created.
word = "Foo"
def redefine_word(block)
word = "Bar"
puts word
block.call
end
redefine_word(lambda { puts word })
You really have to take care of the scope, when you send a block to a function. Consider the output:
Bar Foo
The difference between lambda and Proc
There is another exciting detail I want to put the finger on. Control keywords like return, raise, break, redo, retry do NOT have any impact on the further execution. And that's an important difference to Procs. A lambda example:
def my_method
puts "before lambda"
my_lambda = lambda do
puts "inside lambda"
return
end
my_lambda.call
puts "after lambda"
end
my_method
returns:
before lambda inside lambda after lambdaAnd now the same snippet with a Proc:
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
returns:
before Proc inside ProcBoom! The "return" inside the Proc prevents executing all following logic (line 8 of "my_method"). Good to know, isn't it? Another important difference concerns the parameters of the block. Lambdas are strict:
my_lambda = lambda { |p1, p2| puts "Parameters: #{p1}, #{p2}" }
my_lambda.call("One")
ends up in an exception:
wrong number of arguments (1 for 2) (ArgumentError)But a Proc is liberal:
my_proc = proc { |p1, p2| puts "Parameters: #{p1} and #{p2}" }
my_proc.call("One")
returns:
Parameters: One andKeep the differences in mind, when you choose a Proc or a lambda for closuring.
Supported by Ruby 1.9.3
Keine Kommentare:
Kommentar veröffentlichen