First-class functions via procs and lambdas
Ruby has first-class support for functions as objects. Functions are represented by the Proc class and can be created in a variety of ways:
# Via Proc.new
proc_from_class = Proc.new { |x| x * 2 }
# => #<Proc:0x00000001260413f8>
# Via Kernel.proc
proc_from_proc = proc { |x| x * 2 }
# => #<Proc:0x00000001260413f8>
# Via Kernel.lambda
proc_from_lambda = lambda { |x| x * 2 }
# => #<Proc:0x00000001260413f8 (lambda)>
# Via the stabby literal
proc_from_literal = ->(x) { x * 2 }
# => #<Proc:0x00000001260413f8 (lambda)>
# Via returned blocks from methods
def make_proc(&block)
block
end
proc_from_block = make_proc { |x| x * 2 }
# => #<Proc:0x00000001260413f8>
# From existing methods via to_proc or &
def double(x)
x * 2
end
proc_from_method = method(:double).to_proc
# => #<Proc:0x00000001260413f8 (lambda)>
We can then invoke these functions via the #call method:
proc_from_class.call(3)
# => 6
# call is also aliased as []
proc_from_proc[4]
# => 8
# and as .(), but looks kinda weird
proc_from_lambda.(10)
# => 20
There is a subtle difference between procs created with Proc.new or proc and those created with the other methods: the former creates non-lambda procs, which do not enforce arity (the number of method arguments) and have different behavior with return and break statements:
lambda_arity = lambda { |x, y| x * y }
lambda_arity.call(2, 3)
# => 6
lambda_arity.call(2)
# => ArgumentError: wrong number of arguments (given 1, expected 2)
proc_arity = proc { |x, y| x * y }
proc_arity.call(2, 3)
# => 6
proc_arity.call(2)
# y is nil, so the body raises:
# => TypeError: nil can't be coerced into Integer
For return, a lambda returns from the lambda itself, but a proc returns from the enclosing method:
def lambda_return
lambda { return 1 }.call
2
end
lambda_return
# => 2 (the lambda returned 1, then the method kept going and returned 2)
def proc_return
proc { return 1 }.call
2
end
proc_return
# => 1 (the proc's `return` exited the whole method)
In general, lambdas are preferred for most use cases.
Another thing to mention is that all procs are closures, meaning they capture the surrounding context where they are defined, including local variables and self. This allows them to access and modify those variables even after the outer method has returned:
def make_counter
count = 0
-> { count += 1 }
end
counter = make_counter
counter.call
# => 1
counter.call
# => 2
History
Proc is one of Ruby's oldest building blocks. Ruby 1.0 already had the Proc class, Proc.new, Proc#call, and the Kernel#proc and Kernel#lambda helpers. However, the proc shorthand actually returned lambdas at this point.
Ruby 1.2 in 1998 introduced Method#to_proc and Ruby 1.4 in 1999 introduced Proc#[].
In Ruby 1.9 in 2007, Kernel#proc was sensibly changed to return non-lambda procs, and the stabby lambda literal syntax was introduced along with the .() call syntax for callable objects.