I thought this was the one that worked?

#!/usr/bin/env ruby

repeat = 1

def run
number_of_times = repeat
number_of_times.downto(0) do
puts number_of_times
sleep 1
end
end

run

Fails: undefined variable, “repeat”
in first line of run method

I would have sworn that this was the
one that worked. I know that for a class
definition, the value of “repeat” isn’t
known in an instance. That makes sense
to me (now).

But here, I’m in a script. I am continually
surprised by this behavior. In my mental
model, the run method is a “subsidiary”
context of the larger context, and as such
it should just “naturally” be aware of values
defined in the wider context.

Obviously, my mental model is way, way off,
which is why I keep getting surprised. Can
anyone enlighten me?

thanks
eric

On Jul 31, 2006, at 2:49 PM, Eric A. wrote:

end
known in an instance. That makes sense
which is why I keep getting surprised. Can
anyone enlighten me?

thanks
eric

repeat is a local variable. class, def, and module introduce a new
scope without closing over their enclosing scope. Blocks introduce a
new scope that does enclose it’s enclosing scope.

repeat = 1 # local variable repeat

def run # I just introduced a new scope. I can’t see local variables
outside my body

define_method(“run”) { # I just introduced a new scope, but I’m also
a closure, I can see repeat.

Note that this issue has nothing to do with instances vs. classes, etc.

On Tue, Aug 01, 2006 at 04:23:27AM +0900, Logan C. wrote:

repeat is a local variable. class, def, and module introduce a new
scope without closing over their enclosing scope. Blocks introduce a
new scope that does enclose it’s enclosing scope.

As I understand it, this means that class, def, and module use dynamic
local scope, and blocks use static/lexical scope. Is that accurate?

On Jul 31, 2006, at 3:30 PM, Chad P. wrote:

On Tue, Aug 01, 2006 at 04:23:27AM +0900, Logan C. wrote:

repeat is a local variable. class, def, and module introduce a new
scope without closing over their enclosing scope. Blocks introduce a
new scope that does enclose it’s enclosing scope.

As I understand it, this means that class, def, and module use dynamic
local scope, and blocks use static/lexical scope. Is that accurate?

All these examples are lexical scoping. Ruby doesn’t really have
dynamic scoping although you can sort of abuse instance variables to
achieve similar effects.

The difference is that blocks are closures, where def, class, and
module aren’t.

On Tue, Aug 01, 2006 at 04:57:48AM +0900, Logan C. wrote:

All these examples are lexical scoping. Ruby doesn’t really have
dynamic scoping although you can sort of abuse instance variables to
achieve similar effects.

The difference is that blocks are closures, where def, class, and
module aren’t.

Wait . . . you mean that all blocks are automagically lexical
closures, as though declared lexical variables within them have gone out
of scope? I imagine I’m probably misunderstanding you, but if not,
that’s a pretty nifty bit of trickery.

On Tue, Aug 01, 2006 at 07:05:31AM +0900, Logan C. wrote:

module aren’t.

Wait . . . you mean that all blocks are automagically lexical
closures, as though declared lexical variables within them have
gone out
of scope? I imagine I’m probably misunderstanding you, but if not,
that’s a pretty nifty bit of trickery.

I’m not sure I understand your question. All blocks (by blocks I mean
do / end and { } ) are (lexically scoped) closures.

I’ll use a Perl example:

sub foo {
my $bar = 1;
return sub { print ++$bar };
}

my $baz = foo();

Voila. $baz contains a lexical closure. This is the case because the
return value from foo() was lexically “closed” by virtue of $bar going
out of scope, but its value still being accessible via the coderef
returned from foo() and assigned to $baz.

On Jul 31, 2006, at 5:13 PM, Chad P. wrote:

closures, as though declared lexical variables within them have
gone out
of scope? I imagine I’m probably misunderstanding you, but if not,
that’s a pretty nifty bit of trickery.

I’m not sure I understand your question. All blocks (by blocks I mean
do / end and { } ) are (lexically scoped) closures.

On Tue, Aug 01, 2006 at 07:54:33AM +0900, Jacob F. wrote:

}
def foo

baz = foo
baz.call # => 2
baz.call # => 3
baz.call # => 4

Who said it’s different? I’m just asking about the foregoing statement
that all blocks are closures (which strikes me as improbable). That’s
like saying that this will generate a closure (which it won’t):

sub foo {
return sub { my $bar = 1; print ++$bar };
}

On 7/31/06, Chad P. [email protected] wrote:

my $baz = foo();

Voila. $baz contains a lexical closure. This is the case because the
return value from foo() was lexically “closed” by virtue of $bar going
out of scope, but its value still being accessible via the coderef
returned from foo() and assigned to $baz.

How is this different from:

def foo
bar = 1
return proc{ bar += 1; puts bar }
end

begin
puts bar
rescue Exception => e
puts e
end

=> undefined local variable or method `bar’ for main:Object

baz = foo
baz.call # => 2
baz.call # => 3
baz.call # => 4

Jacob F.

On Jul 31, 2006, at 7:07 PM, Chad P. wrote:

my $bar = 1;
returned from foo() and assigned to $baz.
rescue Exception => e
statement
that all blocks are closures (which strikes me as improbable). That’s
like saying that this will generate a closure (which it won’t):

sub foo {
return sub { my $bar = 1; print ++$bar };
}

In ruby it does. I’m having difficulty thinking of a simple example
to demonstrate it, but basically it grabs the whole environment
whether theres a reference to a variable or not. It does this to
allow things like:

def foo
x = 1
lambda { puts eval(“X”.downcase) }
end

You might say, so it just notices that you’re using eval. But
consider this:

def bar
x = 1
lambda { puts send(“lave”.reverse, “y”.sub(/y/, ‘x’)) }
end

Obviously contrived examples, but this is part of the reason blocks
“leak” memory.

On Jul 31, 2006, at 6:48 PM, Chad P. wrote:

do / end and { } ) are (lexically scoped) closures.
Voila. $baz contains a lexical closure. This is the case because the
return value from foo() was lexically “closed” by virtue of $bar going
out of scope, but its value still being accessible via the coderef
returned from foo() and assigned to $baz.

Yes. It is just like perl.

% cat closure.rb
def foo
bar = 1
lambda { puts (bar += 1) }
end

baz = foo()

baz.call
baz.call

% ruby closure.rb
-:13: warning: don’t put space before argument parentheses
2
3

On Tue, Aug 01, 2006 at 09:57:03AM +0900, Logan C. wrote:

You might say, so it just notices that you’re using eval. But
consider this:

def bar
x = 1
lambda { puts send(“lave”.reverse, “y”.sub(/y/, ‘x’)) }
end

Obviously contrived examples, but this is part of the reason blocks
“leak” memory.

Um, no . . . that’s not the equivalent of what I just posted. To make
it equivalent, you’d have to do something like this:

def foo
lambda { x = 1; puts eval(“X”.downcase) }
end

On Tue, Aug 01, 2006 at 10:15:09AM +0900, Just Another Victim of the
Ambient M. wrote:

}

Okay, the mere fact that you "used a Perl example" demonstrates that 

there is a miscommunication going on here. Why would an example from Perl
clear anything up? It’s a different language with different semantics. Are
you hoping that we all know Perl?

I’m hoping that demonstrating how it does or does not work in Perl will
make it clear what I’m talking about, based on similar syntax between
the languages, so that I can find out what does and does not work in
Ruby. Duh?

I suspect what's happening here is that we're mixing up code blocks with 

“Ruby blocks.”
These are examples of what most programmers would call blocks but are
not Ruby blocks:

I know there’s a difference, thanks. The problem is that nobody seems
to be addressing the fact that for a proper closure, as I understand it,
the closure variable has to go out of scope while the block of code does
not. If Ruby blocks do something automagical to make variables declared
within them go out of scope while the block is still in scope, I’d like
to know. If there’s some other way to “close” the block’s data while
the block is still available, I’d like to know that, too.

These are Ruby blocks:

[1, 2, 3].each do |i|
# this is a Ruby block and
# this is a closure
end

So explain how it is a closure. Please.

some_local_variable = 2
func = lambda { puts some_local_variable } # a one line block and closure

Am I to assume that some_local_variable is going out of scope outside of
the lambda declaration at some point, to create that closure?

All things that are called "blocks" in Ruby are closures.
Do you still have any questions on the matter?

Yes. Are you just failing to explain how these things are closures, or
do you not know what a closure is? You keep telling me blocks are
closures somehow, but you’re not explaining how. Saying it doesn’t make
it so. Please explain what I’m missing.

“Chad P.” [email protected] wrote in message
news:[email protected]

Who said it’s different? I’m just asking about the foregoing statement
that all blocks are closures (which strikes me as improbable). That’s
like saying that this will generate a closure (which it won’t):

sub foo {
return sub { my $bar = 1; print ++$bar };
}

Okay, the mere fact that you "used a Perl example" demonstrates that

there is a miscommunication going on here. Why would an example from
Perl
clear anything up? It’s a different language with different semantics.
Are
you hoping that we all know Perl?

I suspect what's happening here is that we're mixing up code blocks 

with
“Ruby blocks.”
These are examples of what most programmers would call blocks but
are
not Ruby blocks:

def some_method_as_function
# code block goes here but
# in the Ruby world, this is not a “block…”
end

while some_condition
# code block goes here but
# in the Ruby world, this is not a “block…”
end

These are Ruby blocks:

[1, 2, 3].each do |i|
# this is a Ruby block and
# this is a closure
end

some_local_variable = 2
func = lambda { puts some_local_variable } # a one line block and
closure

All things that are called "blocks" in Ruby are closures.
Do you still have any questions on the matter?

Chad P. wrote:

Yes. Are you just failing to explain how these things are closures, or
do you not know what a closure is? You keep telling me blocks are
closures somehow, but you’re not explaining how. Saying it doesn’t make
it so. Please explain what I’m missing.

I’m unfamiliar with your assertion that the context has to go
out of scope before a closure exists.

Not trying to argue, just stating my perception.

Maybe you can point us to a formal definition somewhere.

I would have said that a closure will retain its variables
if/when they go out of scope.

Bad analogy: We might loosely define a car as “a machine that
goes places,” but it’s still a car even when it sits still.

My impression is that you’re applying the definition too
rigidly.

Again, I’m not certain I’m right. No flames, no insults.

Hal

On Tue, Aug 01, 2006 at 09:50:23AM +0900, Logan C. wrote:

dynamic scoping although you can sort of abuse instance
that’s a pretty nifty bit of trickery.

% cat closure.rb
% ruby closure.rb
-:13: warning: don’t put space before argument parentheses
2
3

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.

On Jul 31, 2006, at 10:18 PM, Chad P. wrote:

return sub { my $bar = 1; print ++$bar };
lambda { puts eval(“X”.downcase) }
Obviously contrived examples, but this is part of the reason blocks
“leak” memory.

Um, no . . . that’s not the equivalent of what I just posted. To make
it equivalent, you’d have to do something like this:

def foo
lambda { x = 1; puts eval(“X”.downcase) }
end

It’s still a closure.

Like I said it’s hard to give you an example, but ruby creates a
closure for a block regardless. That lambda still has a reference to
the enclosing scope of foo, even if their are no variables there. Ok
I came up with a good one:

% cat closure2.rb
class A
def initialize
@a = 1
end

def foo
lambda { puts @a }
end

def set_var(val)
@a = val
end
end

a = A.new
baz = a.foo
baz.call

a.set_var( “Hello” )

baz.call

% ruby closure2.rb
1
Hello

In this case it happens to be closing over “self”, but since this is
ruby there is always a self, all blocks are closures. (and you
always have the associated overhead)

Hi -

On Tue, 1 Aug 2006, Chad P. wrote:

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

Here’s some sort of negative evidence:

def foo
lambda { puts bar }
end

bar = 1
foo.call # error: bar is undefined

Here, the statement “puts bar” is executed in the context of the
creation of the block (rather than the context of its execution) –
and since there’s no bar there, an exception is raised.

Some subtle but possible interesting hair-splitting:

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.

(Like I said, subtle hair-splitting :slight_smile:

David

On Jul 31, 2006, at 10:30 PM, Chad P. wrote:

All these examples are lexical scoping. Ruby doesn’t really have
of scope? I imagine I’m probably misunderstanding you, but if
my $bar = 1;
returned from foo() and assigned to $baz.
baz = foo()
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.


CCD CopyWrite Chad P. [ http://ccd.apotheon.org ]
“It’s just incredible that a trillion-synapse computer could actually
spend Saturday afternoon watching a football game.” - Marvin Minsky

Oh yeah, here’s another example:

def foo
return lambda { puts eval(“x”) }, binding
end

closure, bnding = foo()
eval(“x = 7”, bnding)

closure.call

Basically, it’s impossible not to create a closure with a block in
ruby, there is always an implicit closure.

   in first line of run method

I would have sworn that this was the
one that worked.

I swear to the heavens that it was an innocent question?
(But I look forward to a clear differentiation
between closures and blocks from the thread that
resulted.)

class, def, and module introduce a new scope
without closing over their enclosing scope.

That was the shift I needed in my mental model.
Thanks much. I expected that behavior from class
and module. I am quite surprised that it is true
for def, as well.

That surprise leads me to ask: Why?
What is it that made that a good idea?

thanks, all
eric

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs