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:...>
# feathersLambdas
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) # => 42Converting 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.