CSC/ECE 517 Fall 2011/ch3 4b js

From Expertiza_Wiki
Revision as of 04:22, 15 October 2011 by Qrjones (talk | contribs)
Jump to navigation Jump to search

Closures

What is a Closure?

A closure is a block of code that can access the lexical environment of its definition. A closure has two properties:

  • A closure can be passed as an object.
  • A closure recalls the values of all the variables that were in scope when the function was created and is able to access those variables when it is called even though they may no longer be in scope.

A closure can be expressed simply as a function pointer that references a block of executable code and the variables from the scope it was created.

Closures in Ruby

Ruby supports closures through use of Procedures, or simply procs, and lambdas, which are Blocks. When creating a lambda or proc, the object holds a reference to the executable block and bindings for all the variables used by the block.

Blocks

Procs and Lambdas

In Ruby, we can create a Proc object explicitly in three different ways.

Proc.new

Using this method involves simply passing in a block, which will return a Proc object that will run the code in the block when you invoke its call method.

pobject = Proc.new {puts “This is a proc object.”}
pobject.call 

proc method

In the Kernel module, we can use the proc method, which is available globally. In Ruby 1.9, it is equivalent to Proc.new, but in Ruby 1.8, it is equivalent to lambda. The difference between proc and lambda will be discussed later.

pobject = proc { puts “Inside the proc object” }
pobject.call 

lambda method

Similar to the proc method, it is globally available in the Kernel module, however, it will create a lambda Proc object.

pobject = lambda { puts “Inside the proc object” }
pobject.call 

procs vs. lambdas

The difference between Procs and Lambdas has to do with their handling of control flow keywords, such as break and return. For instance, the first example below shows the difference in behavior using the return keyword. With the proc method, the return not only returns from the proc method, but also the enclosing method, which is shown when the last puts is not called.

def my_method
  puts "before proc"
  my_proc = Proc.new do
    puts "inside proc"
    return
  end
  my_proc.call
  puts "after proc"
end
 
my_method
user@user-ubuntu:/home/user/ruby$ ruby a.rb
before proc
inside proc

If we exchange the proc for the lambda method, the return only returns from the lambda method and NOT the enclosing method, thus, it continues on to execute the last puts .

def my_method
  puts "before proc"
  my_proc = lambda do
    puts "inside proc"
    return
  end
  my_proc.call
  puts "after proc"
end
 
my_method
user@user-ubuntu:/home/user/ruby$ ruby a.rb
before proc
inside proc
after proc

If we go back to the proc method, and use the break keyword in lieu of return . However, instead of returning from the proc method and the enclosing method, we are issued a LocalJumpError . Since break keywords are usually used to fall out of an iteration, but it is not contained within an iteration, Ruby throws an error.

def my_method
  puts "before proc"
  my_proc = Proc.new do
    puts "inside proc"
    break
  end
  my_proc.call
  puts "after proc"
end
 
my_method
user@user-ubuntu:/home/user/ruby$ ruby a.rb
before proc
inside proc
a.rb:64:in `block in my_method': break from proc-closure (LocalJumpError)
    from a.rb:66:in `call'
    from a.rb:66:in `my_method'
    from a.rb:70:in `<main>'

Let us revisit the lambda method, but this time, we will use the break keyword. You will notice that the break is treated like the return keyword, where the execution is dumped out of the lambda, but continuous executing the rest of the enclosing method.

def my_method
  puts "before proc"
  my_proc = lambda do
    puts "inside proc"
    break
  end
  my_proc.call
  puts "after proc"
end
 
my_method


user@user-ubuntu:/home/user/ruby$ ruby a.rb
before proc
inside proc
after proc

Why use Closures?

Currying

Object-Oriented Programming in Ruby

Classes

Attributes

Inheritance

Access Control

Abstract Methods

References

Flanagan, D and Matsumoto, Y, (2008). The Ruby Programming Language, O’Reilly Media, Inc., Fitzgerald Michael, (2007). Learning Ruby, O’Reilly Media, Inc., (example)