Community Oriented

Gems

Web Based

Projects For Me

lambda, proc, and Proc.new

The difference between Ruby closure types, 15 Aug 2011

What is the difference between the many kinds of procs in Ruby? I realized while doing Ruby Kickstart that I didn't know. Did some research, and for each of these, there are two things to consider, how do they handle mismatched parameter arity, and how do they handle return statements.

lambda use this if you want it to behave like a method

Return statements return from the lambda.

def who_returns
  lambda { return "lambda" }.call
  return "method"
end

who_returns # => "method"

Like methods, you cannot mismatch parameter arity.

lambda { |one, two| }.call(1)
# ~> wrong number of arguments (1 for 2) (ArgumentError)

proc avoid this since its behaviour differs across commonly used versions

In 1.8, it behaves like lambda and returns from the block. In 1.9, it behaves like Proc.new and returns from the environment.

def who_returns
  proc { return RUBY_VERSION + " proc" }.call
  return RUBY_VERSION + " method"
end

who_returns # => "1.8.7 method" # also for 1.8.6
who_returns # => "1.9.3 proc" # also for 1.9.1 and 1.9.2

In 1.8, it behaves like lambda and raises an error. In 1.9, it behaves like Proc.new and sets mismatched args to nil.

RUBY_VERSION                            # => "1.8.7"
proc { |one, two| [one, two] }.call(1)
# ~> wrong number of arguments (1 for 2) (ArgumentError)


RUBY_VERSION                            # => "1.9.3"
proc { |one, two| [one, two] }.call(1)  # => [1, nil] 

Proc.new use this if you want it to behave like a block

Return statements return from the environment.

def who_returns
  Proc.new { return "Proc.new" }.call
  return "method"
end

who_returns # => "Proc.new"

Like blocks, you can mismatch parameter arity.

Proc.new { |one, two| [one, two] }.call(1) # => [1, nil]

-> (stabby lambda) use it if you want method behaviour and you're in 1.9

The stabby lambda is just a 1.9 alternate syntax for lambda, so use it if you want method behaviour.

def who_returns
  -> { return "lambda" }.call
  return "method"
end

who_returns # => "method"

As a lambda, you can't mismatch arity.

->(one, two) { }.call(1)
# ~> wrong number of arguments (1 for 2) (ArgumentError)
blog comments powered by Disqus