Ruby Examples > Procs and Lambdas

#---Procs and Lambdas---

Procs and Lambdas are similar to blocks in that they too are anonymous functions.
But blocks have some limitations:

  • They can’t be assigned to a variable
  • You can only pass at most one block to a function
  • They can’t be returned from a function
  • They can’t be passed to another proc/function
  • They are not objects

Hence why we have procs and lambdas. They are proper object representations of a ruby block.

Here’s how you create a block that’s a proc:

one_adder = proc { |x| x + 1 }

And here’s how you’ll call this proc that’s assigned to a variable:

p one_adder.call(41) # => 42

You can also call it in these other shorthand ways:

p one_adder.(41) # => 42
p one_adder[41] # => 42

Here’s how you create a block that’s a lambda:

perimeter = lambda { |l, b| 2 * (l + b) }
p perimeter.(3, 6) # => 18

The words proc and lambda in the examples above are not ruby keywords. They are methods in the Kernel module.

You can use the “stabby lambda” syntax ->() {} to create a lambda concisely:

perimeter = ->(l, b) { 2 * (l + b) }
p perimeter.(3, 6) # => 18

Converting a block to a proc

When a function is passed a block, and if that block needs to be passed as argument to yet another function, then you’ll have to convert the passed-in block to a proc.
That’s done by defining a variable for it and prefixing it with &.

Function block_to_proc has no intention of calling the passed-in block for its result (using yield).
Instead it just wants to pass it as an argument to another function truth_teller.
So it converts the block to a proc and puts it into a variable a_proc_from_a_block with this syntax: &a_proc_from_a_block

def block_to_proc(name, &a_proc_from_a_block)
  hi = truth_teller(a_proc_from_a_block)
  "block_to_proc says to #{name}: #{hi}"
end
def truth_teller(a_proc)
  "#{a_proc.call('Dwayne')}, U can't act"
end
res = block_to_proc('The Rock') do |name|
  "hello #{name}"
end
p res
## "block_to_proc says to The Rock: Dwayne, U can't act"

Converting a proc to a block

Let’s say the truth_teller above is re-defined to work with a block instead of a proc, like so:

def truth_teller
  "#{yield('Dwayne')}, U can't act"
end

Then, in block_to_proc, you’ll have convert the proc back to block before passing it to truth_teller using the same & syntax quirk:

def block_to_proc(name, &a_proc_from_a_block)
  hi = truth_teller(&a_proc_from_a_block)
  "block_to_proc says to #{name}: #{hi}"
end

Procs vs Lambdas

Procs and Lambdas differ in how they treat the arguments and the keywords return and break.
For the most part, you don’t have to worry about this. Just stick with lambdas if you don’t want to be caught by any surprises.
Check the “Lambda and non-lambda semantics” section of the official doc for the differences.

Next example: Regular Expressions.