Question about closure

S

Sam Sungshik Kong

Hi, group!

I am trying to understand what exactly a closure is.
I'm kinda familiar with C#.
In C# 2.0 (the next version that's coming out), there's a anonymous
delegate.
People say that it's a closure (See
http://martinfowler.com/bliki/Closures.html).
They even compare it with Ruby codes saying that closure is block.
Is it true?

When I saw the closure example in Ruby, it was not just a block.

Here's a typical example of Ruby closure.

<snip>
def makeCounter
var = 0
lambda do
var +=1
end
end

c1 = makeCounter
c1.call
c1.call
c1.call

c2 = makeCounter

puts "c1 = #{c1.call}, c2 = #{c2.call}"
</snip>


Here is what the above page(http://martinfowler.com/bliki/Closures.html)
says...

<snip>
Closures have been around for a long time. I ran into them properly for the
first time in Smalltalk where they're called Blocks. Lisp uses them heavily.
They're also present in the Ruby scripting language - and are a major reason
why many rubyists like using Ruby for scripting.

Essentially a closure is a block of code that can be passed as an argument
to a function call.

....

In a language that has Closures, in this case Ruby, I'd write this.

def managers(emps)
return emps.select {|e| e.isManager}
end
</snip>

This is just a block, right?
Is it also a closure?

I'm confused.
Can somebody enlighten me?


Sam
 
F

Florian Gross

Sam said:
Hi, group!
Moin!

In a language that has Closures, in this case Ruby, I'd write this.

def managers(emps)
return emps.select {|e| e.isManager}
end
</snip>

This is just a block, right?
Yes.

Is it also a closure?

In Ruby all blocks are also closures, but in that example you wouldn't
need a closure.

Here's a sample that really needs closures to work:

sum = 0
[1, 2, 3].each do |item|
sum += item # access to a variable that is outside of the block
end

This is a closure because you are accessing an outer variable from
within the block.

Blocks in Ruby are a fancy syntax for anonymous functions with closures.

JavaScript's anonymous functions also hold closures.

Let's add a Ruby-like Array#each to JavaScript:

Array.prototype.each = function(block) {
for (var index = 0; index < this.length; ++index) {
var item = this[index]
block(item, index)
}
return(this)
}

Then we can use it like this:

var sum = 0
[1, 2, 3].each(function(item) { sum += item })

Here again the outer variable "sum" gets accessed from within an
anonymous function. For this to work it has to hold a closure.

Back to your sample from earlier:
def makeCounter
var = 0
lambda do
var +=1
end
end

lambda takes a block and converts it into an Object that can be returned
and later invoked via .call. The closure will also get stored.

This lets you increase the var which is scoped locally to makeCounter
from outside of it by calling the lambda.

Here's another example of a closure:

def times_lambda(a)
lambda { |b| a * b }
end

times_5 = times_lambda(5)
times_5.call(4) # => 20
times_5.call(6) # => 30

times_lambda() returns a lambda that holds a reference to the a
parameter of times_lambda() and multiplies it with the b parameter that
is later given to the lambda itself.

Hope this helps. If you still have any questions, feel free to ask.

Regards,
Florian Gross
 
P

Phil Tomson

<snip>
def makeCounter
var = 0
lambda do
var +=1
end
end

c1 = makeCounter
c1.call
c1.call
c1.call

c2 = makeCounter

puts "c1 = #{c1.call}, c2 = #{c2.call}"
</snip>

In this case makeCounter returns a lambda (an anonymous function, which
is also known as a closure). Notice that closures can carry around
information from the scope they are defined in - so var is first defined
outside of the lambda 'block', but even when this closure is returned
outside of that scope it still knows about var.

The part between the do ... end in the method above is that block.
Here is what the above page(http://martinfowler.com/bliki/Closures.html)
says...

<snip>
Closures have been around for a long time. I ran into them properly for the
first time in Smalltalk where they're called Blocks. Lisp uses them heavily.
They're also present in the Ruby scripting language - and are a major reason
why many rubyists like using Ruby for scripting.

Essentially a closure is a block of code that can be passed as an argument
to a function call.

...

In a language that has Closures, in this case Ruby, I'd write this.

def managers(emps)
return emps.select {|e| e.isManager}
end
</snip>

This is just a block, right?

This -> {|e| e.isManager} is the block.
Is it also a closure?

I guess I would kind of think of it as the definition or blueprint for
the closure - Is it really a closure before it gets turned into a proc
or lamda?
The emps object responds to a select method call.
The definition of select might look like (2 alternatives):

#using yield:
def select
#develop some variable var
yield var
end

#alternatively, it could be defined by
#explicitly requiring a block to be passed in:
def select &b
#develop some variable var
b.call(var)
end

The second alternative is probably more instructive for our purposes.
The '&' before the 'b' indicates that the select method takes a block as
a parameter - as the block is passed in it is transformed into a Proc
object and it become a closure (at least that's the way I think of it).
However, the block will still carry around the context (variables defined
in the scope where the block was defined) where it was defined.

Phil
 
S

Sam Sungshik Kong

It's unbelievable that you answered my question only in 5 minutes with such
a hugh content....:)
I'm still trying to understand it.
I may ask you additional questions.

Thank you so much.

Sam

Florian Gross said:
Sam said:
Hi, group!
Moin!

In a language that has Closures, in this case Ruby, I'd write this.

def managers(emps)
return emps.select {|e| e.isManager}
end
</snip>

This is just a block, right?
Yes.

Is it also a closure?

In Ruby all blocks are also closures, but in that example you wouldn't
need a closure.

Here's a sample that really needs closures to work:

sum = 0
[1, 2, 3].each do |item|
sum += item # access to a variable that is outside of the block
end

This is a closure because you are accessing an outer variable from
within the block.

Blocks in Ruby are a fancy syntax for anonymous functions with closures.

JavaScript's anonymous functions also hold closures.

Let's add a Ruby-like Array#each to JavaScript:

Array.prototype.each = function(block) {
for (var index = 0; index < this.length; ++index) {
var item = this[index]
block(item, index)
}
return(this)
}

Then we can use it like this:

var sum = 0
[1, 2, 3].each(function(item) { sum += item })

Here again the outer variable "sum" gets accessed from within an
anonymous function. For this to work it has to hold a closure.

Back to your sample from earlier:
def makeCounter
var = 0
lambda do
var +=1
end
end

lambda takes a block and converts it into an Object that can be returned
and later invoked via .call. The closure will also get stored.

This lets you increase the var which is scoped locally to makeCounter
from outside of it by calling the lambda.

Here's another example of a closure:

def times_lambda(a)
lambda { |b| a * b }
end

times_5 = times_lambda(5)
times_5.call(4) # => 20
times_5.call(6) # => 30

times_lambda() returns a lambda that holds a reference to the a
parameter of times_lambda() and multiplies it with the b parameter that
is later given to the lambda itself.

Hope this helps. If you still have any questions, feel free to ask.

Regards,
Florian Gross
 
B

Bill Atkins

Methods aren't closures in Ruby - only blocks are. In that example,
the makeCounter method is returning a lambda, which is a block (and
thus a closure). A closure is (from what I understand) just a block
that remembers its context. Consider this:

a = 34
b = proc { a * 2 }

# in a different scope
b.call # = > 68

Even though a has gone out of scope by the time b is actually called,
Ruby saves the value of a with b so that when you call it, b can
return the proper value. In other words, a closure is just a block
that refers to its environment.

Bill
 
P

Phlip

Sam said:
Can somebody enlighten me?

In addition to the other (unread) answers:

X = 42

oval.bind('Button-1') {
|event|
doc(event)
puts x.inspect()
}

Ruby statements between { and } (or begin and end) form an object, called a
block, which passes into any method on its left. That method can evaluate
the statements inside the block immediately, and can store the block as an
object, called a Proc, so something can call it later. The block links to
instances of variables seen from functions around it, such as our x, even
after such functions return. Each instance of the block links to a parallel
instance of each variable, so such variables persist until the block itself
destroys. Languages such as Perl and Smalltalk also use these "block
closures".

They are more than a convenience: Variables must always have the narrowest
scope possible, and variables linked to a block, such as x, have the
narrowest conceivable scope over an indefinite lifespan.
 
F

Florian Frank

You and Mr. Gross helped me understand what a closure is.
Thanks a lot!

By the way, where does the name - closure come from?
It's not a very intuitive name, IMO.

A closure is a combination of an anonymous function and the
lexical environment it was created in. You could say it's a closure
around this lexical environment (=all the current bindings of local
variables/all the nested environments) at that moment. If you
have a method like

def foo; end

its lexical environment does only exist while executing the method. But
you can also return the environment if you for example use

def foo;binding;end
# => nil
foo
# => #<Binding:0x402aed74>
foo
# => #<Binding:0x402adf8c>

That opens a lot of possibilities, because you can still hold a
reference to the environment after the method call was executed. If
you have real closures you also have object oriented programming.
A small example is this stack implementation:

def make_stack
data = []
lambda do |id,*args|
case id
when :push then data.push *args
when :pop then data.pop
when :top then data.last
end
end
end
# => nil

s1 = make_stack
# => #<Proc:0x402af044@(irb):3>
s2 = make_stack
# => #<Proc:0x402af044@(irb):3>
s1[:push, 1, 2, 3]
# => [1, 2, 3]
s2[:push, 'a', 'b', 'c']
# => ["a", "b", "c"]
s1[:top]
# => 3
s2[:top]
# => "c"
s2[:pop]
# => "c"
s1[:top]
# => 3
s2[:top]
# => "b"

Note that s1 and s2 are two different stack objects, because
they access a different environment and thus a different data variable.

You might be interested in reading the wizard book
http://mitpress.mit.edu/sicp/full-text/book/book.html,
especially chapter 4, "The Metacircular Evaluator".
 
S

Sam Sungshik Kong

Florian Frank said:
You and Mr. Gross helped me understand what a closure is.
Thanks a lot!

By the way, where does the name - closure come from?
It's not a very intuitive name, IMO.

A closure is a combination of an anonymous function and the
lexical environment it was created in. You could say it's a closure
around this lexical environment (=all the current bindings of local
variables/all the nested environments) at that moment. If you
have a method like

def foo; end

its lexical environment does only exist while executing the method. But
you can also return the environment if you for example use

def foo;binding;end
# => nil
foo
# => #<Binding:0x402aed74>
foo
# => #<Binding:0x402adf8c>

That opens a lot of possibilities, because you can still hold a
reference to the environment after the method call was executed. If
you have real closures you also have object oriented programming.
A small example is this stack implementation:

def make_stack
data = []
lambda do |id,*args|
case id
when :push then data.push *args
when :pop then data.pop
when :top then data.last
end
end
end
# => nil

s1 = make_stack
# => #<Proc:0x402af044@(irb):3>
s2 = make_stack
# => #<Proc:0x402af044@(irb):3>
s1[:push, 1, 2, 3]
# => [1, 2, 3]
s2[:push, 'a', 'b', 'c']
# => ["a", "b", "c"]
s1[:top]
# => 3
s2[:top]
# => "c"
s2[:pop]
# => "c"
s1[:top]
# => 3
s2[:top]
# => "b"

Note that s1 and s2 are two different stack objects, because
they access a different environment and thus a different data variable.

Thank you for the great explanation.
Now I'm close to full understanding...:=)
You might be interested in reading the wizard book
http://mitpress.mit.edu/sicp/full-text/book/book.html,
especially chapter 4, "The Metacircular Evaluator".

Wow.
Seems like this book is just what I've been looking for.
Not just for closures but for general concepts of programs.
Thanks.

Sam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top