I thought this was the one that worked?

A

ara.t.howard

That still doesn't make all blocks closures, though.

really?


harp:~ > cat a.rb
class Object
def closure(&block) block end
end

p(eval('self', closure))

class C
p(eval('self', closure))
end


harp:~ > ruby a.rb
main
C

any block encloses, at minimum, 'self'. therefore all blocks are closures.

-a
 
C

Chad Perrin

Yes, this is exactly the point we've been trying to get across. Both
of these are closures.


This is where we get into what David Black described as hair
splitting. Lets move away from each, and to a set of more general
methods:

Let's not. Hair splitting actually came up in reference to the
distinction between the first two examples, and not in reference to the
third. If you're calling the distinction for the third example "hair
splitting", I'm just going to have to call you flat-out "wrong", unless
this is a case of "the Ruby community uses a definition of 'closure'
that is in direct contradiction of other definitions of 'closure'",
which seems really odd to me since Ruby most definitely *is* capable of
proper closures as defined elsewhere.
 
L

Logan Capaldo

If that's the case, then *everything else* is a closure too, because
everything else has access to a -- at least where lexical or global
scope exists.

Actually no one has access to a because it is a local variable.

Look all blocks close over at _least_ self. If a block contains a
call to any receiverless method it is a closure even by your rigid
definition.

 
J

Jacob Fugal

The current definition on Wikipedia is scattered, vague, and without
salient points on this matter. I've read through the thing from end to
end, and the article spends an awful lot of time failing to concretely
define a closure.

On that, we can agree. :)
That's a definition of a closure that I would at this point at least not
call "wrong", even if it doesn't strike me as particularly "right"
either, because the explanations of closures I've seen can potentially
be interpreted in that manner. Even so, I'd say that to fit a strict
definition of a closure, the chunk of code in question needs to exit its
enclosing scope before it's a closure -- else it's not "closed".

I don't necessarily agree with that, but it's incidental to my point,
so I won't argue it.
Even then, an empty environment can't exist in Ruby. There's always at
least one "variable" in the environment that will be accessible in the
closure: self. Take the following example:
[snip example]

Now you're arguing that there does, indeed, have to be a variable.
What?

No, I'm not saying there *has* to be a variable for it to be a
closure. I'm simply demonstrating that in Ruby there always *will* be
a variable: self.
In any case, this can happen in Ruby:

class Foo
def bar
lambda { puts "quux" }
end
end

foo = Foo.new
bar = foo.bar

bar.call

. . . so I don't see your point. Cut out the middleman, and it still
works.

Ah, but you're still using self in that example. Who is the receiver
of the call to puts inside the block? It's self.

There is no such thing as a "function" in ruby; they are all methods.
When you make a method call without an explicit receiver, that method
is called with a receiver of self. Even puts; the Kernel module
defines a puts method, which is mixed into the Object class, so all
objects have access to that puts method. That's what some other
posters were demonstrating when they used all that trickery redefining
puts for the object's singleton. You're still using self. I was just
trying to make that dependence on self more explicit by using a
non-standard method like baz.

Jacob Fugal
 
A

ara.t.howard

We're back to the absurdly broad here:

If any "thing" that has access to another scope is a closure, that makes
every nested "thing" in a language with global and/or lexical scope a
"closure". That's a little like defining a "human" as "has four limbs".

closures in ruby have neither global nor lexical scope though:


harp:~ > cat a.rb
class Object
def closure(&b) b end
end

c = closure

def a() p 42 end
eval 'a', c

def a() p 'forty-two' end
eval 'a', c



harp:~ > ruby a.rb
42
"forty-two"


the scoping is dynamic. in otherwords we can add things to the enclosed state
later - it's not frozen at the time the closure is created.

that can refine the def a bit.

regards.

-a
 
C

Chad Perrin

I'm joining the party late, but try this example:

Why? Why should we keep trying unnecessarily complex examples that
introduce a bunch of variables (in the statistical study sense of the
term) that are not strictly relevant to the point under consideration?
I'm frankly getting a little tired of having someone new enter the
conversation every few hours and say "Let's try this discussion," after
which I have to expend energy on several emails back and forth to get
the broad, complex example offered narrowed down to the salient points,
over and over again -- especially since the salient points are the same
in each case. One step forward, three steps back.

From the Wikipedia definition:

[A] closure is a function that refers to free variables in its
lexical context.

Also from the Wikipedia definition:

[A] closure is a function

That's not very useful. The Wikipedia "description" (it's not a
dictionary, and as such doesn't strictly speaking aim to "define" the
terms contained within it) is, for purposes of this discussion,
nigh-uselessly broad and lacking in coherent detail.

Even if the Ruby block itself contains no reference to free variables,
the stored lexical context associated with the block does so
implicitly. In the case of:

array.each do
puts "each!"
end

the block may be get executed immediately w/o referencing free
variables, but the ruby implementation has no way of knowing that.
Thus, every block carries around a lexical context which references
all free variables in that context. Thus, every block is a closure.

Only if you accept a description of a closure as a definition. As I
implied elsewhere, however, "has four limbs" may be an accurate
description of a human, but the fact "dog" fits that description doesn't
make it a human.
 
C

Chad Perrin

closures in ruby have neither global nor lexical scope though:

harp:~ > cat a.rb
class Object
def closure(&b) b end
end

c = closure

def a() p 42 end
eval 'a', c

def a() p 'forty-two' end
eval 'a', c

harp:~ > ruby a.rb
42
"forty-two"


the scoping is dynamic. in otherwords we can add things to the enclosed
state
later - it's not frozen at the time the closure is created.

that can refine the def a bit.

That's not much of a closure, then.
 
C

Chad Perrin

Actually no one has access to a because it is a local variable.

Look all blocks close over at _least_ self. If a block contains a
call to any receiverless method it is a closure even by your rigid
definition.

The "a" to which I referred was the "a" that existed at "a = 1".
 
A

ara.t.howard

If that's the case, then *everything else* is a closure too, because
everything else has access to a -- at least where lexical or global scope
exists.

'has access to' and 'keeps a pointer to' are to totally separate things and
is, i believe, the crucial difference between what constitues a concrete
closure. for instance

this_is_a_closure = lambda{}

why? read the c code and see that the object indeed contains a pointer to
'this' context that can be referred to in a dynamic (looking up anything
that's been added) way.


now, this is __not__ a closure because no object exists, specially not the
object 'b', which remembers or stores a pointer to the enclosing environment
that contains a. the context was not stored and is lost

a = 42

b = a + 42


the key thing to remember is that, indeed, any ruby statement has to potential
to become an 'enclosing' object since the environment can always be stored
with a simple

@b = binding

nevertheless, not all statements are closures because not all of them choose
to remember this environment.

blocks however, due to the magic ruby does under the hood and the fact that
they must remain valid arguments to

eval some_code, a_binding_or_proc

do maintain a pointer to the enclosing environment which contains at minimum
'self'.

regards.


-a
 
C

Chad Perrin

On that, we can agree. :)
Good.



I don't necessarily agree with that, but it's incidental to my point,
so I won't argue it.

I was overhasty in the way I phrased that, I think. I suppose the chunk
of code doesn't need to exit its enclosing scope so much as the
reference to the closure scope has to exit that scope irrevocably.

Ah, but you're still using self in that example. Who is the receiver
of the call to puts inside the block? It's self.

That's an impressive bit of gymnastics. I don't buy it as satisfying
the requirements of a closure, though, at this point. Self is just
something within the current scope, and we're back to an absurdly broad
redefinition of "closure".

There is no such thing as a "function" in ruby; they are all methods.

Methods are "functions" in the technical, broadly interpreted computer
science definition of the term. They're just a special case of
"function" that requires more specific conditions to qualify as
"methods". A method is a function: a function is not necessarily a
method.
 
J

Jacob Fugal

Let's not. Hair splitting actually came up in reference to the
distinction between the first two examples, and not in reference to the
third.

Actually, if you go back and read David's post [ruby-talk:205331],
which is the first reference to hair splitting in this thread, you'll
see that he clearly believes both of the first two examples to be
closures. When he mentions hair splitting, it's directly in relation
to the third form -- an unconverted (yielded to) block.
If you're calling the distinction for the third example "hair
splitting", I'm just going to have to call you flat-out "wrong"

Did you read my explanation? I called it hair-splitting for the same
reason David did -- because it can be argued both ways. I gave both
reasons. If you want to debate that point, please reply with more
specifics.
unless this is a case of "the Ruby community uses a definition of 'closure'
that is in direct contradiction of other definitions of 'closure'"

I'll repeat myself: "Since the environment is never stored, it's not
really a closure *in the implementation*. This is the hair that David
was splitting.

"But semantically, whether a block is converted to a proc or just
yielded to, the behavior regarding variable scope is identical; so if
one is a closure, it's useful to refer to the other as a closure as
well, even if it's not implemented as a true closure. In this sense,
all blocks are closures."

As you can see, I've admitted that in the *one* case of a
non-converted block it is not a true closure. But I believe semantic
terms can be more useful than rigid and narrowly defined formal
theoretical definitions. Like duck typing -- as long as it quacks just
like a real closure, it's close enough for me.

Jacob Fugal

[ruby-talk:205331]
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/205331
 
C

Chad Perrin

no.

def x
puts a
end

is __lexical__ scoping. not dynamic.

It's not lexical scoping if that "a" variable is separate from the "a"
variable in the enclosing scope.
 
A

ara.t.howard

That's not much of a closure, then.

that's an absurd thing to say don't you think? it's not bad or good - it is
what it is. it is in fact a very pure closure which perfectly captures the
state in which it was defined in. note that i said it captures the 'state'
and not the 'state of the state' - in otherwords it has a pointer to the state
and not a copy of the state. that way it even has access to newly added
information as my example shows. this is amazingly powerful even if it
doesn't fit your idea of what a closure may or may not be.

i might add that perl has exactly this kind of enclosing semantics and is
considered to have 'true' closures.

-a
 
C

Chad Perrin

that's an absurd thing to say don't you think? it's not bad or good - it is
what it is. it is in fact a very pure closure which perfectly captures the
state in which it was defined in. note that i said it captures the 'state'
and not the 'state of the state' - in otherwords it has a pointer to the
state
and not a copy of the state. that way it even has access to newly added
information as my example shows. this is amazingly powerful even if it
doesn't fit your idea of what a closure may or may not be.

No, I don't think it's "an absurd thing to say" -- it just doesn't have
much depth. The depth is this:

If it doesn't provide what OOPish programmers would call "protection",
it's not a closure. How can it be a closure if it's not closed?

i might add that perl has exactly this kind of enclosing semantics and is
considered to have 'true' closures.

True -- but that doesn't mean that "this kind of enclosing semantics" is
the closure itself. See above, re: closing something to create a
closure.
 
A

ara.t.howard

It's not lexical scoping if that "a" variable is separate from the "a"
variable in the enclosing scope.

yes. it is, because there is no 'a' in the enclosing dynamic scope:

harp:~ > cat a.rb
a = 42

def m() p a end

m

harp:~ > ruby a.rb
a.rb:4:in `m': undefined local variable or method `a' for main:Object (NameError)
from a.rb:6


you have to understand that ruby doesn't always use one method of scoping -
sometimes it's dynamic and sometimes it's lexical.

-a
 
L

Logan Capaldo

It's not lexical scoping if that "a" variable is separate from the "a"
variable in the enclosing scope.


Ah this is where you misunderstand. def does not close over a. defs
introduce a new "toplevel" scope.
 
C

Chad Perrin

Let's not. Hair splitting actually came up in reference to the
distinction between the first two examples, and not in reference to the
third.

Actually, if you go back and read David's post [ruby-talk:205331],
which is the first reference to hair splitting in this thread, you'll
see that he clearly believes both of the first two examples to be
closures. When he mentions hair splitting, it's directly in relation
to the third form -- an unconverted (yielded to) block.

You were right, up to the point where you said "When he mentions hair
splitting". The problem at that point that prompted him to mention hair
splitting was the fact that I was balking at defining that second
example as a "closure". I've now come to the conclusion that the second
example is a closure according to at least some, valid from a given
perspective, interpretations of the meaning of "closure". Thus, I quit
splitting that hair and said "Okay, so I'll stipulate that the second
example can be called a closure, depending on interpretation."

Did you read my explanation? I called it hair-splitting for the same
reason David did -- because it can be argued both ways. I gave both
reasons. If you want to debate that point, please reply with more
specifics.

See above.
 
C

Chad Perrin

yes. it is, because there is no 'a' in the enclosing dynamic scope:

harp:~ > cat a.rb
a = 42

If there's no "a", then perhaps you can tell me what the hell that is.
 

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,773
Messages
2,569,594
Members
45,114
Latest member
GlucoPremiumReview
Top