Skip to content

Instantly share code, notes, and snippets.

@tmikeschu
Last active May 5, 2017 19:39
Show Gist options
  • Save tmikeschu/1edc0dafce76aaf51ef450cb9525989c to your computer and use it in GitHub Desktop.
Save tmikeschu/1edc0dafce76aaf51ef450cb9525989c to your computer and use it in GitHub Desktop.

Procs and Lambdas in Ruby

Procs

adder = Proc.new { |arg1, arg2| arg1 + arg2 }

Procs in Ruby are like anonymous functions. In other words, little packages of code (defined in blocks of {} or do..end) that can be passed around as an object. Proc is actually short for procedure, so when you pass a Proc as an argument to a method, you can think of it as giving the method a list of instructions, as opposed to a particular data structure or value.

Lambdas

adder = -> arg1, arg2 { arg1 + arg2 } # This is called "stabby lambda" syntax
adder = lambda { |arg1, arg2| arg1 + arg2 } # literal syntax

adder.call(1,2)
# => 3

# "do" and "end" still apply
adder = -> arg1, arg2 do
  result = arg1  + arg2
  result
end

adder.call("a", "b")
# => "ab"

Lambdas are just special types of Procs, with these key differences:

  • Argument quantity matters for a lambda. If you pass the wrong amount, you get an error. Not the case with Procs.
  • A return statement in a lambda returns from the scope of the lambda, while a Proc return escapes from the current method.

In my opinion, lambdas are cleaner and stricter, which is a good thing. You are held accountable to the arguments you expect, and the return is more contained.

Array.map

doubler = -> number { number  * 2 }
ages = [ 15, 32, 13 ]
ages.map(&doubler)
# => [ 30, 64, 26 ]

There's the magic. We set a lambda block to the variable doubler, which expects a number argument. We pass this as an argument to ages.map, with & declaring doubler as a Proc type.

Enumerable Power

words = ["apple", "okay", "not", "yes", "forgettable"]

def longer_than(number)
  -> word { word.length > number }
end

words.all?(&longer_than(5))
  #=> false
  
words.all?(&longer_than(2))
  #=> true
  
words.select(&longer_than(3))
  #=> ["apple", "okay", "forgettable"]
  
words.reject(&longer_than(3))
  #=> ["not", "yes"]
  
words.one?(&longer_than(5))
  #=> true

Beautifully DRY. Lambdas allow us to reuse logic for any number of higher-order functions like enumerables. (Higher-order functions take functions as arguments).

Try to complete this challenge by calling a lambda in any enumerable you use.

Further Reading

Understanding Blocks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment