I thought this was the one that worked?

C

Chad Perrin

because in the original code

a = 42

def m
puts a
end

'a' will only be lexically scoped - and throw and error of course. the
previous def of 'a' is totally superfluous - i was just pointing out that
the
failure of ruby to find 'a' is going to be a failure of lexical scoping
rules
because there is no enclosing scope (well nothing named in it yet) where an
'a' is defined.

Ahh, I see where you were going. You were demonstrating that the "a" in
the scope of "m" is separate from the "a" outside of it, but didn't
really explicitly state that. I have a tendency to forget that def
creates a "new top level" scope, and need reminders.

I'm relieved to discover that Ruby isn't defaulting to dynamic scope in
the previous example after all. Thanks for the explanation.
 
C

Chad Perrin

Ahh, I see where you were going. You were demonstrating that the "a" in
the scope of "m" is separate from the "a" outside of it, but didn't
really explicitly state that. I have a tendency to forget that def
creates a "new top level" scope, and need reminders.

gsub /state/, 'explain'

I apologize for any confusion my imprecise phrasing may have caused.
 
A

ara.t.howard

We're discussing "closures", not "enclosures".

they are intimately related:


http://en.wikipedia.org/wiki/Scope_(programming)

...

Static scoping

With static scoping, a variable always refers to its nearest
***enclosing** binding. This is a property of the program text and
unrelated to the runtime call stack. Because matching a variable to its
binding only requires analysis of the program text, this type of scoping
is sometimes also called lexical scoping. Static scope is standard in
modern functional languages such as ML and Haskell because it allows the
programmer to reason as if variable bindings are carried out by
substitution. Static scoping also makes it much easier to make modular
code and reason about it, since its binding structure can be understood in
isolation. In contrast, dynamic scope forces the programmer to anticipate
all possible dynamic contexts in which the module's code may be invoked.

Correct implementation of static scope in languages with first-class
nested functions can be subtle, as it requires each function value to
carry with it a record of the values of the variables that it depends on
(the pair of the function and this environment is called a ***closure***).
When first-class nested functions are not used or not available (such as
in C), this overhead is of course not incurred. Variable lookup is always
very efficient with static scope, as the location of each value is known
at compile time.

...
Two definitions of "closure" from the American Heritage Dictionary of
the English Language:

A bringing to an end; a conclusion: finally brought the project to
closure.

The property of being mathematically closed.

In fact, the term "closure" in computer science is derived from the
mathematical definition of "closure", as in "a closed system". A closure in
computer science is code and data that constitute a closed system.

no, that's simply not correct. the basis for the word 'closure' in computer
science refers to 'enclosing' the present scope.

take

http://www.perl.com/pub/a/2002/05/29/closure.html

as an example of this interpretation.

As David has suggested (without specifically and explicitly saying it
outright in such terms), the data in question might consist of a sort of
"potential data" such that a closure's referent closed scope needn't
necessarily actually contain anything, so long as the scope itself is
theoretically present and accounted for.

and 'scope' is the key here. closure in computer science refers to enclosing
the present scope.
If anything, it's you who's introducing pollutants to the otherwise clearer
(if not actually clear) subject by confusing "enclosure" with "closure".

well, at the risk of sounding inflamatory, you're example and comments so far
have shown a decided lack of understanding about ruby's scoping rules and how
they related to a (common) notion of closure which is not 'closed' but is
enclosing.

your critique leaves one asking: what do __you__ think a closure should be
since what a closure actually is in ruby, perl, and many functional languages
is not closed at all.

in any case it's my hope that people realize that, whatever you call it,
ruby's closures do, in fact, act to enclose the existing scope and never
freeze or copy it.

regards.

-a
 
L

Logan Capaldo

In the hope that eventually an example might satisfy your all your
criteria and demonstrate why Ruby blocks are closures. And at the

The equivalent of line noise, distracting from the actual point of
discussion, doesn't help.

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.

How's this one from the Free On-line Dictionary of Computing?:

closure

1. <programming> In a reduction system, a closure is a data
structure that holds an expression and an environment of
variable bindings in which that expression is to be
evaluated. The variables may be local or global. Closures are
used to represent unevaluated expressions when implementing
functional programming languages with lazy evaluation. In a
real implementation, both expression and environment are
represented by pointers. [1]


It, like basically every other definition I've run across, doesn't
actually address the salient points. May I please speak with David
again? He at least was discussing something precise enough to be
on-topic for the point of contention.

Oh, I see the problem: metaphysically you're more of an essentialist
and I'm more of a functionalist. Alas, this can only end in
tears. ;-)

I'm also more of a prescriptivist than a descriptivist in natural
linguistic terms. I like precision in my understanding when
discussing
technical topics. "It shares some characteristics with something
someone once called a closure!" isn't enough for me.

I was the person who originally said "every block in ruby is a
closure". Apparently our definition of the word "closure" disagrees.
Fine. Let me amend my statement:

"Every block in ruby is a closure according to my (Logan Capaldo's)
understanding of the concept of closure, and of how how ruby blocks
are implemented. I make no guarantees that my definition will match
yours, nor will I entertain the thought that there is a definitive
definition of 'closure', especially in light of languages like Ruby."

Given all these facts, in my opinion this thread should end, and if
you want to continue having your conversation about the meta-physical
nature of a closure, you should start a new thread or take it off
list. I do not moderate this list though and that is just my opinion.



 
C

Chad Perrin

they are intimately related:

So are "sex" and "reproduction", but they're not the same thing, and
they are defined differently. Thus, just as the definition of
"reproduce" doesn't provide a definition of "sex", so too "enclosure"
doesn't provide a definition of "closure".

no, that's simply not correct. the basis for the word 'closure' in computer
science refers to 'enclosing' the present scope.

take

http://www.perl.com/pub/a/2002/05/29/closure.html

as an example of this interpretation.

That's a howto for creating closures, not an authoritative reference on
the history of the term "closure". It doesn't even prove your point,
for that matter.

and 'scope' is the key here. closure in computer science refers to
enclosing
the present scope.

No, it refers to "closing" the scope, not "enclosing" the scope. To
enclose the scope, you have to be outside of it. To close the scope,
you seal it up so that stuff doesn't wander in and out of it. By the
same token, if you close a door, you seal the passage against traffic in
and out: if you enclose a door, you're probably wrapping it up for
shipping.

well, at the risk of sounding inflamatory, you're example and comments so
far
have shown a decided lack of understanding about ruby's scoping rules and
how
they related to a (common) notion of closure which is not 'closed' but is
enclosing.

I don't assume that to have inflammatory intent. I only assume you're
confused about the difference between "close" and "enclose".

your critique leaves one asking: what do __you__ think a closure should be
since what a closure actually is in ruby, perl, and many functional
languages
is not closed at all.

Read Intermediate Perl, then come back and say that again.

I will quote from its original version (which actually had a different
title, but it's still the first edition of Intermediate Perl) for you:

The kind of subroutine that can access all lexical variables that
existed at the time it was declared is called a _closure_ (a term
borrowed from the world of mathematics).

. . and again:

This subroutine is a closure because it refers to the lexical $count
variable.

At the end of the naked block, the $count variable goes out of scope.
However, because it is still referenced by the subroutine in
$callback, it stays alive, now as an anonymous scalar variable.

Here's another quote from the same book:

Closures are "closed" only on lexical variables, since lexical
variables eventually go out of scope. Because a package variable
(which is a global) never goes out of scope, a closure never closes on
a package variable. All subroutines refer to the same single instance
of the global variable.

(meaning: global to the "package", aka "namespace")

Here's yet another:

A subroutine doesn't have to be an anonymous subroutine to be a
closure. If a named subroutine accesses lexical variables and those
variables go out of scope, the named subroutine retains a reference to
the lexicals, just as you saw with anonymous subroutines.

There are four distinct sections of Chapter 6: Subroutine References
that deal specifically with closures -- thus the wealth of quotes on the
subject.

In case you're wondering about the credentials of the author of this
book, his name is Randal L. Schwartz. You may have heard of the
"Schwartzian transform".
 
J

Just Another Victim of the Ambient Morality

Chad Perrin said:
I don't. A closure is a closure whether you use it or not, just as a
remote control for the TV is a remote control for the TV whether you use
it or not. What's actually relevant to the discussion is more like the
question of whether a remote control for the TV is still a remote
control for the TV if it was built with no TV on which it could operate.

I think 3 is a better example because in all the examples of (alleged)
closures we've given each other, there usually was a TV... I mean, a
context...

variable = 2 # this is the context

[1, 2, 3].each do |i|
# it sounds as if you think this is the "context"
puts i + variable

# either way, we're using the context so
# we agree that this is a closure
end

Actually . . . no. If that was a closure just because there was a
variable nearby that it could access, then in any script that contains a
lexical variable at the "base level" of the script, and in any script
that has global variables, every scope enclosed within the scope of the
script would be a closure.

One step forward, two steps back...
I thought I had demonstrated that blocks passed into the "each" method
of class "Array" were closures? Do you think the following two situations
are the similar?


context = 2

if some_condition
# this is not a Ruby block nor is it a closure...
puts context
end

[1, 2, 3].each do |i|
# this is a block and is also a closure
puts context * i
end


The two code blocks (not Ruby blocks) above look similar but are very
different.
The "if" keyword is a language construct and does not take a block. I
cannot change the behaviour of "if."
In contrast, "each" is not a keyword and is not a language construct. I
may redefine (or define!) it and change its behaviour. It is a simple
method and, within it, created its own scope which is outside the closing
scope of the closure (block) passed in... We don't see that here but that's
not relevant. It happens nonetheless...

Unfortunately, it was David and possibly one or two others who have been
instrumental in narrowing it down. You're still talking about things
that don't seem to bear on what I was saying at all.

Why is this unfortunate?
I only assumed I had something to do with it because you came to the
quoted conclusion while responding to my post. This is usually
reasonable...

Not to be insulting, but I don't think you've grasped the fact that
there's more to being a closure than being a language construct that
someone once said was a closure.

I've demonstrated how it was a closure in previous posts. You said you
were "digesting" it so I ceased to expand on it. Have you digested them and
decided they were not closures?
 
C

Chad Perrin

I think 3 is a better example because in all the examples of (alleged)
closures we've given each other, there usually was a TV... I mean, a
context...

That's why I went back to correct my analogy, such that in the new
version the TV exists, and the mechanism for a relationship between the
remote and the TV exists, but the actual existence of anything to pass
back and forth does not. The TV is context, but the channel, volume,
and power variants of the TV are what the context contains, and the
buttons on the remote are its interaction with those things.

The two code blocks (not Ruby blocks) above look similar but are very
different.
The "if" keyword is a language construct and does not take a block. I
cannot change the behaviour of "if."
In contrast, "each" is not a keyword and is not a language construct. I
may redefine (or define!) it and change its behaviour. It is a simple
method and, within it, created its own scope which is outside the closing
scope of the closure (block) passed in... We don't see that here but that's
not relevant. It happens nonetheless...

Okay, so the fact that .each has its own scope differentiates it from a
situation involving a mere conditional statement. I'll stipulate that
for now (I'll probably agree more thoroughly later, when I've had a
chance to consider the mechanics of scope for methods such as "each").
If such a relationship to a method is a necessary precondition of an
idiomatic Ruby "block", complete with a thus-enclosing scope that ends
while the block persists, I think we may finally have an almost-explicit
case for *why* and *how* an idiomatic Ruby "block" is, necessarily, a
"closure" -- assuming of course David's suggestion of a closed lexical
scope as the necessary ingredient of a closure, rather than specifically
the de-scoped variable within that lexical scope.

That's some interesting, complex set of explanations for how a closure
is achieved, but it's valid as far as I can see, and it does indeed seem
to indicate that all Ruby blocks are closures.

Thank you.

Why is this unfortunate?
I only assumed I had something to do with it because you came to the
quoted conclusion while responding to my post. This is usually
reasonable...

It's not strictly speaking unfortunate in the general case -- it just
seemed that your commentary was "unfortunately" largely irrelevant to
that narrowing. You've certainly contributed positively to the
discussion, however, with the above discussion of the .each method.
 
A

ara.t.howard

No, it refers to "closing" the scope, not "enclosing" the scope. To enclose
the scope, you have to be outside of it. To close the scope, you seal it up
so that stuff doesn't wander in and out of it.

and yet

harp:~ > ruby -e' closure = lambda{}; def a() 42 end; eval "p a", closure; '
42

harp:~ > ruby -e' def a() 42 end; closure = lambda{}; eval "undef a", closure; a() '
-e:1: undefined method `a' for main:Object (NoMethodError)

stuff wanders in, stuff wanders out.

same goes for perl, lisp, etc, etc. they, like ruby, have 'real' closures.
closures are not closed in that (dynamic) sense.

what the 'closed' in closure means is that you cannot get 'out' of it. in
otherwords

harp:~ > ruby -e' closure = lambda{}; eval "a, b = 40, 2; c = a + b; p c", closure; p c '
42
-e:1: undefined local variable or method `c' for main:Object (NameError)

in mathmatical terms operations on members of the set produces more members of
that set (meaning in that scope here).

I don't assume that to have inflammatory intent. I only assume you're
confused about the difference between "close" and "enclose".

well - i think i understand exactly how closures work to enclose a given scope
in ruby while 'closing' nothing but lexical definitions - so we'll have to
agree to disagree here.

Read Intermediate Perl, then come back and say that again.

I will quote from its original version (which actually had a different
title, but it's still the first edition of Intermediate Perl) for you:

The kind of subroutine that can access all lexical variables that
existed at the time it was declared is called a _closure_ (a term
borrowed from the world of mathematics).

the term, not the exact meaning. topo maps have closures too.

This subroutine is a closure because it refers to the lexical $count
variable.

At the end of the naked block, the $count variable goes out of scope.
However, because it is still referenced by the subroutine in
$callback, it stays alive, now as an anonymous scalar variable.

Here's another quote from the same book:

Closures are "closed" only on lexical variables, since lexical
variables eventually go out of scope. Because a package variable
(which is a global) never goes out of scope, a closure never closes on
a package variable. All subroutines refer to the same single instance
of the global variable.

(meaning: global to the "package", aka "namespace")

indeed. and this is like ruby, which is also closed on lexical variables
__only__. note that this is not closed


harp:~ > cat a.pl
$s = sub{ a(); };

sub a { print "42\n"; };

&$s;


harp:~ > perl a.pl
42

the created closure encloses the scope at the time of creation - including both
lexical and dynamic scopes - to which the subroutine 'a' is added. the lexical
scope is indeed closed though.

Here's yet another:

A subroutine doesn't have to be an anonymous subroutine to be a
closure. If a named subroutine accesses lexical variables and those
variables go out of scope, the named subroutine retains a reference to
the lexicals, just as you saw with anonymous subroutines.

There are four distinct sections of Chapter 6: Subroutine References
that deal specifically with closures -- thus the wealth of quotes on the
subject.

not very much info on dynamic scoping though - the main focus is on lexical
scoping.
In case you're wondering about the credentials of the author of this
book, his name is Randal L. Schwartz. You may have heard of the
"Schwartzian transform".

i've read the book many times - i was perl hacker before coming to ruby.

-a
 
J

Just Another Victim of the Ambient Morality

Chad Perrin said:
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".

Again, there is context (in the English sense of the word) to what I
said that. In fact, it looks like you've narrowed into a specific part of
the paragraph while ignoring other parts of that very same paragraph... If
we have access to a scope _from_another_scope,_ then we are a closure. I do
not think this is absurdly broad...
"if" and "while" (code) blocks don't introduce a new scope, which
explains why they have access to their environments...
 
C

Chad Perrin

not very much info on dynamic scoping though - the main focus is on lexical
scoping.

That's because it's about closures, which are not closures due to
anything involving dynamic scope. They're closures due to something
involving a closed lexical scope.

There's another subthread that looks a lot more promising for clarifying
whether idiomatic Ruby "blocks" are necessarily closures than this is
proving to be, so I'm afraid I've only skimmed your email. I can
multitask pretty well, but trying to follow all the subthreads that
arise when thirty people all jump in to try to "prove" that all blocks
are closures via a variety of approaches that, for the most part, don't
seem to prove any such thing, is producing more tasks than I can
simultaneously manage very well (when combined with the actual
money-making stuff I need to do). I apologize for my lack of attention
to the details of your email at this time.
 
C

Chad Perrin

Again, there is context (in the English sense of the word) to what I
said that. In fact, it looks like you've narrowed into a specific part of
the paragraph while ignoring other parts of that very same paragraph... If
we have access to a scope _from_another_scope,_ then we are a closure. I do
not think this is absurdly broad...
"if" and "while" (code) blocks don't introduce a new scope, which
explains why they have access to their environments...

Define "from another scope", then. The program as a whole is a scope,
after all -- "another scope", when you're in some other scope contained
within the program's scope.
 
C

Chad Perrin

<snip>

Does that mean this enormous thread is drawing to a close (pun possibly
intended)? :)

I hope so. Every relationship needs closure. Ahem.

It probably would have been much shorter if someone had been making
these points about the relationship of methods to blocks and lexical
scopes from the beginning -- instead, most of the discussion consisted
of largely unexplained, and often overly complex, examples that didn't
actually address the why/how question(s) necessary to illustrate the
underlying principles.
 
H

Hal Fulton

Chad said:
How's this?:

Closure
A "closure" is an expression (typically a function) that can have
free variables together with an environment that binds those
variables (that "closes" the expression).

I found it on this page:

http://jibbering.com/faq/faq_notes/closures.html

I also found this:

http://www.perl.com/pub/a/2002/05/29/closure.html





My understanding is that the vehicle is a car, and the use of it is a
drive (to the country, or whatever). Similarly, a block of code that
can be passed around like a first-class member is a block, or lambda, or
whatever you want to call it today: if you pass it to a function as an
argument, it's a callback, and if you lexically close it, it's a
closure.

I think "lexically" might be the key word there. Isn't it true
that Perl has only lexical closures, not "real" closures?
I suppose that's possible, but I really don't think so. Do you have a
formal definition of a closure that specifically contradicts my
understanding?

Well, I would say the definition you offered above. It says that
a closure *can* have free variables, not that it must. All of the
internal housekeeping (as I understand it) is done the same for a
Ruby block with variables as for one without. (Besides, as someone
pointed out, there is always a "self" at the very least.)


Hal
 
H

Hal Fulton

Chad said:
Okay, let's translate that question into the terms we're actually
discussing.

1. If a tree falls in the forest, and there's no one around to hear
it, does it still make a sound?

2. If a lambda has the ability to access its context, but there isn't
any context to access, is it still a closure?

But there's always context. Even an empty block { }
occurring somewhere in a real program has context.


Hal
 
J

Just Another Victim of the Ambient Morality

Jacob Fugal said:
# 3) block yielded to
def baz
yield "world"
end

David's point, however, is that in the third example, when yield is
used instead of converting it to a block, the code inside the block
never really leaves the context in which it is created, because of the
way non-converted blocks are implemented. More specifically, that
implementation doesn't need to store that environment. This is a
probable reason for the speed difference between converted blocks
(first class procs) and unconverted blocks (yield). Since the
environment is never stored, it's not really a closure *in the
implementation*. This is the hair that David was splitting.

Maybe you know more about the implementation of blocks than I do but I
find it hard to believe that yielded blocks don't store a reference to their
environment. I mean, they were able to access it, right? How does it do
that without that reference?

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.

I believe that, when describing a programming language and its features,
the behaviour of the language is more important than its implementation. I
mean, the language is defined by its specification rather than some
implementation, right?
 
C

Chad Perrin

I think "lexically" might be the key word there. Isn't it true
that Perl has only lexical closures, not "real" closures?

Lexical closures *are* "real" closures. The term "closure" as it is
being bandied about is an abbreviation for "lexical closure".
 
C

Chad Perrin

If you two agree then... why don't you improve it? It's a wiki, after
all...

I probably will. Doing so during this discussion would have come off as
trying to "cheat", though.
 
D

dblack

Hi --

# this is the sample code you provided...

a = 10
# the block is defined here but "sent" to the "each" method...
[1, 2, 3].each {|x| puts x * a }

I would say: control passes to the block. The block itself is not
represented by an object (which I think is the only quasi-objective
[ha ha] definition of "sent") in any scope other than the one in which
it was created.


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

dblack

Hi --

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.

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

No, I meant that my comments about whether blocks were closures was
hair-splitting. (Maybe the fact that I introduced the comments that
way looked like I was actually summing up what came before, but the
hair-splitting pronouncement ended with a colon :)


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.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,021
Latest member
AkilahJaim

Latest Threads

Top