CSC/ECE 517 Fall 2011/ch4 4b ds
Wiki textbook chapter on OOLS Lecture 5. Covers the basic of closures and blocks, currying and OOP in Ruby.
Introduction
Closures
A closure is a block of code that “closes over”. This means it can access the lexical environment of its definition. A closure may be defined in one scope and get called outside this scope. Thus a closure retains the values of all the variables that were in scope when the closure was defined. Closures help in making the code short such that one can do more with less code. Ruby supports closures through Blocks and Procs.
Blocks
A block is a set of Ruby statements either between braces or a do/end pair, and appear only immediately after a method invocation. Ruby uses the following standard - braces for single-line blocks and do/end for multiline blocks.
{ puts "Hello World" } # braces block do { puts "Hello World 1" } # do/end block { puts "Hello World 2" } { puts "Hello World 3" } end
Blocks can be instantiated as a Proc object using the Proc or lambda method. The block is then bound to a set of local variables. Once bound, the block code may be called in different contexts through these set variables.Using the example mentioned in lecture 5 in class.
# Class to generate adders class AdderGen def initialize(n) @block = lambda {|a| n + a} end def add(a) @block.call a end end twoAdder = AdderGen.new 2 incrementer = AdderGen.new 1 puts incrementer.add(4) puts twoAdder.add(6)
Output 5 8
@block is the Ruby closure that gets initialized when the lambda method gets called through the class initialize method. The block remembers the parameter with which the initialize method was called even after the initialize method exits. This value of the block is used during the add method invocation.
Procs And Lambdas
There are three ways to create a Proc object in Ruby.
Proc.new
Proc.new takes in a block and returns a Proc object which will run the code in the block when call methodis invoked.
proc_object = Proc.new {puts "Create Proc.new object"} proc_object.call
Proc method
The proc method is equivalent to Proc.new in Ruby 1.9, but in Ruby 1.8 it is equivalent to lambda.
proc_object = proc {puts "Create proc from Proc method"} proc_object.call
Lambda method
This creates a proc object using the lambda method
proc_object = lambda {puts "Create proc from Lambda method"} proc_object.call
Currying
Currying is concept of creating a new function out of an existing function by fixing the value of some of its input parameters. Currying thus makes a generic function more specific to ones needs. Consider the following example where we have a Proc for addition of two numbers. Using currying we can fix the value of the first argument so that when the curried function is called later on with only one argument, it can use the earlier fixed value as the other argument for its addition. Ruby 1.9 allows the creation of a curry-able proc by calling the curry method on it.
add = lambda {|a,b| a + b} puts add[1,2] curried_add = add.curry add_to_ten = curried_add[10] add_to_twenty = curried_add[20] puts add_to_ten[5] puts add_to_twenty[5]
Output 3 15 25