Re: I thought this was the one that worked?



Hi --

On Tue, 1 Aug 2006, Just Another Victim of the Ambient Morality wrote:


<dblack@xxxxxxxxxxxx> wrote in message
news:Pine.LNX.4.64.0608010732450.7358@xxxxxxxxxxxxxx

<dblack@xxxxxxxxxxxx> wrote in message
news:Pine.LNX.4.64.0607312255430.32274@xxxxxxxxxxxxxx

Of course, not all blocks end up getting turned into Proc objects;
some remain just syntactic constructs:

a = 1
[1,2,3].each {|x| puts x + a }

I guess you could debate whether that block is a closure, since it
never leaves the context where it's created -- so there's nothing
really remarkable about the fact that a is still visible inside it.
And every time you put its closureness to the test, so to speak,
you've turned it into a Proc, so technically the Proc, rather than the
block, is the closure.

I would debate that it _is_ a closure because, although it's defined
where its context is, that's irrelevant. What matters is that the block
is
passed into the "each" method of the Array class and is executed there,
where "a" is not visible. Thus, the block was executed outside of the
scope
of "a" while still having access to it. How is this possible? It's
possible because the block that was passed in is a closure...
QED.

It's not exactly passed to the method, though. You can capture it in
the method -- in which case, it becomes a Proc object, and then
there's no issue (hair-splitting or otherwise) about its being a
closure.

If you don't capture it, you can yield to it -- but then you're
yielding to the block, not calling a Proc object derived from the
block.

...and this would be a problem if the definition of a closure is the
calling of a Proc object derived from a block. Alas, that is _not_ the
definition of a closure...
When we yield to the block, we are doing so in our method, which is
_not_ the same scope as the scope where the block was created. Yet, the
block we're yielding to still has access to that other scope. How? Because
it is a closure...

You could say, though, that when you do this:

def x
a = 1
puts a
end

def y
x
end

you're calling x from your method y, and x has access to local
variables not defined in y, so x must be a closure.


It comes down to the fact that blocks are syntactic constructs, while
Procs are first-class objects.

I'm not sure why this has anything to do with anything...

Consider an if statement:

y = 1
if x
y
end

The code in the middle is flat, as regards scope. Furthermore, you
can't do anything with it; you can't send that chunk of code
somewhere, open it up, and find y. It's just an expression or
statement among other expressions or statements.

A code block has one foot in that camp. When you see:

a = 10
[1,2,3].each {|x| puts x * a }

you're seeing, in a sense, a flat scope -- that is, the variable a
just gets used, as it might if it were in an if statement.

That's only part of the story, though. The other parts are, first,
that variables created inside the block are not in scope when the
block exits (so its scope is definitely not flat); and, second, the
fact that it's so easy to convert a block to a Proc that blocks feel
like first-class objects, even though they aren't.


David

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
----> SEE SPECIAL DEAL FOR RUBY/RAILS USERS GROUPS! <-----
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
http://www.manning.com/black => book, Ruby for Rails
http://www.rubycentral.org => Ruby Central, Inc.

.



Relevant Pages

  • Re: I thought this was the one that worked?
    ... not calling a Proc object derived from the ... ...and this would be a problem if the definition of a closure is the ... _not_ the same scope as the scope where the block was created. ... The code in the middle is flat, ...
    (comp.lang.ruby)
  • Re: I thought this was the one that worked?
    ... I guess you could debate whether that block is a closure, ... you've turned it into a Proc, so technically the Proc, rather than the ... not calling a Proc object derived from the ... It comes down to the fact that blocks are syntactic constructs, ...
    (comp.lang.ruby)
  • Re: I thought this was the one that worked?
    ... I guess you could debate whether that block is a closure, ... not calling a Proc object derived from the ... calling of a Proc object derived from a block. ... _not_ the same scope as the scope where the block was created. ...
    (comp.lang.ruby)
  • Re: Function question - final part (closure)
    ... if I now take 'foo' in function bar and replace it with foo's ... scope chain at that point is stored as part of it, ... creates a closure containing the scope at that point. ... which the global scope didn't. ...
    (comp.lang.javascript)
  • Re: I thought this was the one that worked?
    ... the term "closure" in computer science is derived from the ... science refers to 'enclosing' the present scope. ... This subroutine is a closure because it refers to the lexical $count ... Closures are "closed" only on lexical variables, ...
    (comp.lang.ruby)