Functional Programming

Procs

Proc class is a built-in Ruby object instances of which (procs) are representations of callable blocks of Ruby code. As all other Ruby objects procs can be stored under a variable or a constant, be an array or a hash value or used as a method or a block argument.

Some of ways of creating a proc is using the Proc #new method or the Kernel #proc method

my_proc = Proc.new { |x| x }
my_other_proc = proc { |x| x }

To call a proc #call method is used.

my_proc.call('Great') # => "Great"

In addition, a proc is created when a block is passed as an argument to a method.

Further, a proc of a special kind - namely lambda - can be created using Kernel #lambda method or a lambda literal syntax.

Procs as Closures

Procs are closures which mean that they are bound to their identifiers (i.e. self objects) current at the time of their creation and they carry with them used within their body variable and constant references to objects available in the scope of place in which they were created.

class Bird
  def fly
    wings = 'feathers'

    Proc.new do
      puts self
      puts wings
    end
  end
end

class Airplane
  def fly
    Bird.new.fly.call
  end
end

Airplane.new.fly.call
# <Bird:...>
# feathers

Lambdas

There is not separate class for lambdas from Proc. Lambdas are just a special kind of Proc class' instances.

Lambdas are special to other procs in the following manner: 1) return in lambdas exits only from the lambda itself but not - as is the case for other kind of procs - from a method or another proc from which they are called, 2) lambdas are strict about arguments they accept - just like methods - which is not the case for other kind of procs.

A lambda can be created in two ways: 1) using lambda reserved word, or 2) a literal syntax ->.

multiply_by_2 = lambda { |a| a * 2 }
multiply_by_3 = ->(a) { a * 3 }

multiply_by_2.call(5) # => 10
multiply_by_2.call # ArgumentError: wrong number of arguments (given 0, expected 1)

def lets_return
  lambda { return 'returned from lambda' }.call
  proc { return 'returned from proc' }.call
  return 'from block'
end

lets_return # => "returned from proc"

Due to its characteristics lambdas are well suited to be used as arguments to methods or procs which then cauld be described as higher order functions.

To check whether a given proc is a lambda the lambda? method is used.

Defining Methods with Procs

A method can be defined using a proc.

multiply_by_2 = proc { |a| a * 2 }
define_method(:times_two, &multiply_by_2)

times_two # ArgumentError: wrong number of arguments (given 0, expected 1)
times_two(21) # => 42

Converting to Procs

Ruby objects that have a method to_proc defined can be converted to procs with & operator. Symbol, Method and Hash are Ruby built-in classes that have to_proc method defined out-of-the-box.