<dblack / wobblini.net> wrote in message 
news:Pine.LNX.4.64.0608010845050.8390 / rubypal.com...
>
>>> 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.

    Now you're narrowly construing my statement to a ludicrous degree. 
There is context to what I said, you know?
    In your example, method "x" has access to variable "a" because that 
variable is in its own context, not its _enclosing_ context.  This is a 
better example:

a = 1
def x
    puts a
end

def y
    x
end


    Then x _will_ be a closure but, then again, we already knew this...


>>> 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 the whole point of closures.  It looks like variable "a" "just 
gets used," even though the process of it being used is quite complex.
    If I understand what you mean by "flat," then it isn't flat.  It only 
_looks_ flat.
    Is this an example of "flat" scope?


a = "foo"
b = a + "bar"
puts b


    It may look "flat" but scopes have come and gone.
    Your example took a block and sent it to the method "each," which has 
it's own scope, where the block would have ordinarily had no hope of 
accessing the variable "a" except that it was a closure...


> 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.

    I'm not certain that the other parts of "the story" are relevant.

    Incidentally, having variables created inside the block be in scope when 
the block exits is planned for Ruby2.  Indeed, if memory serves me, it is 
Matz's "most regretting" design decision that it doesn't already do this... 
So, I guess it will then be "flat."
    Personally, I look forward to this feature...