CSC/ECE 517 Fall 2011/ch4 4b ds

From Expertiza_Wiki
Revision as of 12:44, 20 October 2011 by Ddilipd (talk | contribs)
Jump to navigation Jump to search

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 method <nowiki>Insert non-formatted text here<nowiki>Insert non-formatted text here</nowiki></nowiki>is 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 the 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