Reason #144 • May 24th, 2026

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:

Ruby
# 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:

Ruby
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:

Ruby
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:

Ruby
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:

Ruby
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.

Reason #145 ?