Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
In Ruby Proc is an object that stores a piece of code (block) and allows it to be executed later. It's like a "stored block" or a "function in a box".
Example 1: we create Proc
say_hello = Proc.new { puts "Hello!" }
say_hello.call
# => "Hello!"
We created a Proc object that stores the code { puts "Hello!" }. Then they called him through .call.
Example 2: Transfer Proc to method
def run_twice(proc)
proc.call
proc.call
end
run_twice(Proc.new { puts "Hi!") })
# => "Hi!"
# => "Hi!"
We passed the block of code as an object and called it several times. This is very convenient when you need to reuse logic.
Proc - why such a name?
It's easier to remember the names of methods when you know what it means. Name Proc in Ruby, it is short for "Procedure" (procedure). In programming languages, since time Lisp i Scheme, term procedure meant "a piece of code that can be executed later" - that is, a function that can be passed as an argument or called.
When Matsumoto (Matz), the creator of Ruby, designed the language, he wanted Ruby to have a simple and flexible way of working with blocks of code. He took the idea of procedures from Lisp/Scheme and made them objects - that's how the class came about Proc (procedure object).
What is Lambda?
Lambda - it's Proc too, but with some differences. It can be created in several ways:
-> { }
say_hi = -> { puts "Hi!" }
say_hi.call
# => "Hi!"
and lambda {}
say_hello = lambda { puts "Hello!" }
Well, to prove that lambda is a proc:
say_hi.class => Proc
The main difference between Proc and Lambda
1. Lambda checks the number of arguments, and Proc - no.
p1 = Proc.new { |a, b| puts a, b }
l1 = ->(a, b) { puts a, b }
p1.call(1)
# => 1
# => nil (the second argument is simply nil)
l1.call(1)
# => ArgumentError: wrong number of arguments
2. return to Proc comes out of the entire method, not just with Proc. In Lambda, return completes only the lambda itself.
And let's consider examples
def test_proc
p = Proc.new { return "From Proc" }
p.call
"After Proc" # this line will not be fulfilled
end
puts test_proc
# => "From Proc"
When Proc calls return, it immediately exits the method in which Proc is created, not just from the block.
return in Lambda completes only the lambda itself
def test_lambda
l = -> { return "From Lambda" }
result = l.call
"After Lambda: #{result}" # this line will be fulfilled
end
puts test_lambda
# => "After Lambda: From Lambda"
Lambda behaves like a normal method: return only completes lambda itself, and the method continues to execute.
& and to_proc
When you transfer an ampersand object to Ruby &, Ruby tries to call on it .to_proc and uses the resulting Proc as a block.
def run(&block)
block.call
end
run { puts "Works!" }
# => "Works!"
Here Ruby automatically called .to_proc for our block { ... } and passed it to the block variable.
This post doesn't have any additions from the author yet.