Hi --

On Tue, 1 Aug 2006, Chad Perrin wrote:

> On Tue, Aug 01, 2006 at 12:05:50PM +0900, dblack / wobblini.net wrote:
>> On Tue, 1 Aug 2006, Chad Perrin wrote:
>>
>>> Okay.  Looks like a closure.  It looks like a closure because of the
>>> relationship of bar to the return-value block of code.  I've been told
>>> that all blocks are closures, though -- and I don't see how it's still a
>>> closure if the "bar = 1" is removed from foo.
>>
>> It's a closure because it carries the context of its creation with it.
>> It doesn't matter whether that context has zero, one, or fifty local
>> variables; the same thing still happens.
>
> It sounds like what you're saying is that the lexical scope of the code
> block (proc/lambda/blah) is what makes it a closure, and not the
> connection with, and OOPish protection/encapsulation of, something that
> started outside the code block and went out of scope externally to the
> code block.

No; what makes something a closure, as I understand it, is that it
carries the context of its creation with it.  Also, there's actually a
difference between a block on the one hand, and a Proc or lambda on
the other.  (See my last couple of posts.)

> I guess that makes a certain amount of sense, but that
> seems like an absurdly broad definition of a closure.  For one thing, it
> would mean that absolutely any unnamed subroutine passed by reference in
> Perl is a closure.  In fact, by the implied definition of a closure that
> produces, this is a closure in Perl:
>
>  sub bar {
>    sub { print "Hello world!\n" };
>  }
>
>  $foo = bar();
>
>  $foo->();
>
> (Yes, I find the dereferencing syntax in Perl to be ugly and cumbersome
> too, but that's beside the point.)
>
> That's the equivalent of this, in Ruby:
>
>  def bar
>    lambda { puts "Hello world!" }
>  end
>
>  foo = bar
>
>  foo.call
>
> (".call" is much prettier than "->()")
>
> Would you say those are both closures?

I agree with Logan that the presence or absence of actual variables
isn't what makes something a closure.  Rather, it's a matter of what's
actually happening in the language.  To me, the distinction you're
describing is sort of like having one class to represent arrays with
one or more elements, and another class to represent empty arrays.
(See also my example with the non-existent bar variable, which
demonstrates that lambdas created in a given context are executed in
that context, with or without local variables.)

I think of a closure as a kind of suitcase: you pack it in one place,
and unpack it somewhere else.   Even if it's empty, though, it's still
a suitcase.

Another way to look at it is this: if you decide that the lambda in
your example above is not a closure, then you have to come up with
separate explanations for everything it does that is closure-like.
If you look at it as a closure, however, there's nothing unaccounted
for.


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.