Ruby1.9 block scope

I could have sworn that one of the firm changes in ruby 1.9 was that variables defined inside a block would also exist outside the block. But when I try it:

>> 1.times{ x=2 }
=> 1
>> x
NameError: undefined local variable or method `x' for main:Object

Did I dream all that? If it wasn't a dream, when and why was that change reversed?

Daniel

I could have sworn that one of the firm changes in ruby 1.9 was that
variables defined inside a block would also exist outside the block

No, it's the reverse. Take this:

x = 5
1.upto(10) { |i| x = i }
puts x

ruby1.8 prints "10", ruby1.9 should print "5".

Hi,

···

In message "Re: ruby1.9 block scope" on Mon, 29 Sep 2008 19:54:43 +0900, Daniel DeLorme <dan-ml@dan42.com> writes:

I could have sworn that one of the firm changes in ruby 1.9 was that
variables defined inside a block would also exist outside the block. But
when I try it:

>> 1.times{ x=2 }
=> 1
>> x
NameError: undefined local variable or method `x' for main:Object

Did I dream all that? If it wasn't a dream, when and why was that change
reversed?

I have once presented a plan to make it work so, but have never
implemented. So it's not "changed reversed". Just the idea
abandoned.

              matz.

James Coglan wrote:

I could have sworn that one of the firm changes in ruby 1.9 was that
variables defined inside a block would also exist outside the block

No, it's the reverse. Take this:

x = 5
1.upto(10) { |i| x = i }
puts x

ruby1.8 prints "10", ruby1.9 should print "5".

Actually you are confusing things a litte. In this case ruby1.9 prints "10". Only the block *parameters* are local to the block:
   >> i = "a"
   => "a"
   >> 2.times{ |i| puts i }
   0
   1
   => 2
   >> puts i
   a

Which is nice, but not nearly as nice as having the variables assigned inside the block available outside of it. These slides are quite old but this was the original plan:
http://www.rubyist.net/~matz/slides/rc2003/mgp00012.html

And I seem to remember I experienced that behavior in 1.9 a few months ago only. But not any more :frowning:

···

--
Daniel

Yukihiro Matsumoto wrote:

···

on Mon, 29 Sep 2008 19:54:43 +0900, Daniel DeLorme <dan-ml@dan42.com> writes:

>I could have sworn that one of the firm changes in ruby 1.9 was that >variables defined inside a block would also exist outside the block. But > when I try it:
>
> >> 1.times{ x=2 }
>=> 1
> >> x
>NameError: undefined local variable or method `x' for main:Object
>
>Did I dream all that? If it wasn't a dream, when and why was that change >reversed?

I have once presented a plan to make it work so, but have never
implemented. So it's not "changed reversed". Just the idea
abandoned.

Ah, ok, then I guess I *did* dream the whole thing. For the record, I think it's a great idea and deserves to be implemented... in ruby 2.0 maybe :wink:

--
Daniel

Hi,

···

In message "Re: ruby1.9 block scope" on Mon, 29 Sep 2008 21:24:02 +0900, Daniel DeLorme <dan-ml@dan42.com> writes:

> >> 1.times{ x=2 }
>=> 1
> >> x
>NameError: undefined local variable or method `x' for main:Object

I have once presented a plan to make it work so, but have never
implemented. So it's not "changed reversed". Just the idea
abandoned.

Ah, ok, then I guess I *did* dream the whole thing. For the record, I
think it's a great idea and deserves to be implemented... in ruby 2.0
maybe :wink:

My vague idea for the issue is that when you see the reference to a
local variable inside of the block, the scope of the variable would be
upgraded to the level of the reference.

              matz.

Yukihiro Matsumoto wrote:

>> I have once presented a plan to make it work so, but have never
>> implemented. So it's not "changed reversed". Just the idea
>> abandoned.
>
>Ah, ok, then I guess I *did* dream the whole thing. For the record, I >think it's a great idea and deserves to be implemented... in ruby 2.0 >maybe :wink:

My vague idea for the issue is that when you see the reference to a
local variable inside of the block, the scope of the variable would be
upgraded to the level of the reference.

Do you mean upgrade the scope of the variable dynamically? Is that even possible? I thought that all local vars had their scope pretty much set in stone at the lexical level. But if you could upgrade their scoping level dynamically... that would be nifty indeed!

···

--
Daniel

Daniel DeLorme wrote:

Yukihiro Matsumoto wrote:

upgraded to the level of the reference.

Do you mean upgrade the scope of the variable dynamically? Is that even
possible? I thought that all local vars had their scope pretty much set
in stone at the lexical level. But if you could upgrade their scoping
level dynamically... that would be nifty indeed!

If he did that , we wouldn't have locals anymore .

···

--
Posted via http://www.ruby-forum.com/\.

Hi,

At Tue, 30 Sep 2008 00:23:17 +0900,
Daniel DeLorme wrote in [ruby-talk:316347]:

> My vague idea for the issue is that when you see the reference to a
> local variable inside of the block, the scope of the variable would be
> upgraded to the level of the reference.

Do you mean upgrade the scope of the variable dynamically? Is that even
possible? I thought that all local vars had their scope pretty much set
in stone at the lexical level. But if you could upgrade their scoping
level dynamically... that would be nifty indeed!

I guess the parser would do it at the compile time.

···

--
Nobu Nakada

Yeah, that would be so... 1970's!

Even javascript seems to finally have abandoned dynamic scoping in
favor of friggin' *ALGOL*'s lexical scoping... I wonder why would ruby
insist on sloppy programming by opening this old can of worms...

···

On Sep 29, 12:23 pm, Daniel DeLorme <dan...@dan42.com> wrote:

Yukihiro Matsumoto wrote:
> >> I have once presented a plan to make it work so, but have never
> >> implemented. So it's not "changed reversed". Just the idea
> >> abandoned.
> >
> >Ah, ok, then I guess I *did* dream the whole thing. For the record, I
> >think it's a great idea and deserves to be implemented... in ruby 2.0
> >maybe :wink:

> My vague idea for the issue is that when you see the reference to a
> local variable inside of the block, the scope of the variable would be
> upgraded to the level of the reference.

Do you mean upgrade the scope of the variable dynamically? Is that even
possible? I thought that all local vars had their scope pretty much set
in stone at the lexical level. But if you could upgrade their scoping
level dynamically... that would be nifty indeed!

Nobuyoshi Nakada wrote:

At Tue, 30 Sep 2008 00:23:17 +0900,
Daniel DeLorme wrote in [ruby-talk:316347]:

My vague idea for the issue is that when you see the reference to a
local variable inside of the block, the scope of the variable would be
upgraded to the level of the reference.

Do you mean upgrade the scope of the variable dynamically? Is that even possible? I thought that all local vars had their scope pretty much set in stone at the lexical level. But if you could upgrade their scoping level dynamically... that would be nifty indeed!

I guess the parser would do it at the compile time.

That was also my guess; it least it's an easy concept to imagine. But it does bring the question of what to do when you *don't* want variables to "escape" into the enclosing scope? e.g.

class Foo
   defined_method :bar do
     x = 1 #I don't want x to be defined in the Foo scope
   end
   defined_method :baz do
     x = 2 #because it would wind up shared with this method
   end
end

The best I could think of was that a variable shouldn't be upgraded if the enclosing scope is a "class" or "module" section. That can be detected at parse time so it would work with lexical binding.

But it would be very interesting indeed if you could bind a block's variables to the enclosing scope dynamically. You could say:
   block.call_using_enclosing_scope #e.g. define_method
   block.call_using_own_scope #e.g. each

To me that feels very very powerful. And more power to the programmer is good, right? :wink:

···

--
Daniel

namekuseijin wrote:

···

On Sep 29, 12:23 pm, Daniel DeLorme <dan...@dan42.com> wrote:

Yukihiro Matsumoto wrote:

My vague idea for the issue is that when you see the reference to a
local variable inside of the block, the scope of the variable would be
upgraded to the level of the reference.

Do you mean upgrade the scope of the variable dynamically? Is that even
possible? I thought that all local vars had their scope pretty much set
in stone at the lexical level. But if you could upgrade their scoping
level dynamically... that would be nifty indeed!

Yeah, that would be so... 1970's!

Even javascript seems to finally have abandoned dynamic scoping in
favor of friggin' *ALGOL*'s lexical scoping... I wonder why would ruby
insist on sloppy programming by opening this old can of worms...

Hehe, you have somewhat of a point. Local variables and proper isolation of scope are pretty important to structured programming. But we weren't talking about a free-for-all opening of all scopes, just about the scope of local variables within *blocks*. I wouldn't much like my method-local variables to creep into the global scope just because I forgot to define them with "var", no thank you.

--
Daniel

Hi,

At Tue, 30 Sep 2008 09:10:39 +0900,
Daniel DeLorme wrote in [ruby-talk:316386]:

class Foo

     define_method :bar do |;x|

     x = 1 #I don't want x to be defined in the Foo scope
   end

     define_method :baz do |;x|

···

     x = 2 #because it would wind up shared with this method
   end
end

--
Nobu Nakada

Hi,

That was also my guess; it least it's an easy concept to imagine. But it
does bring the question of what to do when you *don't* want variables to
"escape" into the enclosing scope? e.g.

class Foo
  defined_method :bar do
    x = 1 #I don't want x to be defined in the Foo scope
  end
  defined_method :baz do
    x = 2 #because it would wind up shared with this method
  end
end

As Nobu stated, you can explicitly declare block local variables,
using ';'. Besides that above code would not share variable x, since
the variable is not used upper level. They are two distinct
variables at the same level, with a same name. See the following
code, that makes a variables shared among blocks:

class Foo
   defined_method :bar do
     x = 1
   end
   defined_method :baz do
     x = 2
   end
   x = 45 # this assignment would make x shared with foo and bar under the new rule.
end

The reason I haven't introduced it yet in Ruby is that single
assignment after the blocks can change the scope of a variable
afterward. Same thing happens assignments _before_ the blocks
already. But I hesitated to enhance that far.

              matz.

···

In message "Re: ruby1.9 block scope" on Tue, 30 Sep 2008 09:10:39 +0900, Daniel DeLorme <dan-ml@dan42.com> writes:

Yukihiro Matsumoto wrote:

As Nobu stated, you can explicitly declare block local variables,
using ';'. Besides that above code would not share variable x, since
the variable is not used upper level. They are two distinct
variables at the same level, with a same name. See the following
code, that makes a variables shared among blocks:

class Foo
   defined_method :bar do
     x = 1
   end
   defined_method :baz do
     x = 2
   end
   x = 45 # this assignment would make x shared with foo and bar under
the new rule.
end

The reason I haven't introduced it yet in Ruby is that single
assignment after the blocks can change the scope of a variable
afterward. Same thing happens assignments _before_ the blocks
already. But I hesitated to enhance that far.

              matz.

Making the scope of x contingent upon what comes later would result, I
believe, in extreme confusion.

Let's say Foo is a large class. Joe Schmo, who did not write Foo, comes
along and adds some code to the bottom, such as the 'x = 45' in your
example. Suddenly there is a bug in Foo. It seems impossible to Joe,
but there it is. He wonders if it is caused by the recent sunspots. He
wraps his computer in tin foil, but to no avail. The tests for bar and
baz still fail as a result of his (obviously, to him) unrelated change.

This was the 'tall' case, but there is also the 'wide' case of deeply
nested scopes. An equal helping of confusion applies here too.

One might argue that when 'x = 45' appears before bar and baz, this
_already_ changes the meaning of bar and baz. But the situation here is
entirely different, in my mind. Don't most of us read code from top to
bottom?

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

···

On Tue, 30 Sep 2008, Yukihiro Matsumoto wrote:

Hi,

In message "Re: ruby1.9 block scope" > on Tue, 30 Sep 2008 09:10:39 +0900, Daniel DeLorme <dan-ml@dan42.com> writes:

>That was also my guess; it least it's an easy concept to imagine. But it
>does bring the question of what to do when you *don't* want variables to
>"escape" into the enclosing scope? e.g.
>
>class Foo
> defined_method :bar do
> x = 1 #I don't want x to be defined in the Foo scope
> end
> defined_method :baz do
> x = 2 #because it would wind up shared with this method
> end
>end

As Nobu stated, you can explicitly declare block local variables,
using ';'. Besides that above code would not share variable x, since
the variable is not used upper level. They are two distinct
variables at the same level, with a same name. See the following
code, that makes a variables shared among blocks:

class Foo
  defined_method :bar do
    x = 1
  end
  defined_method :baz do
    x = 2
  end
  x = 45 # this assignment would make x shared with foo and bar under the new rule.
end

The reason I haven't introduced it yet in Ruby is that single
assignment after the blocks can change the scope of a variable
afterward. Same thing happens assignments _before_ the blocks
already. But I hesitated to enhance that far.

Please continue to hesitate :slight_smile: That would be very hard to deal with.
As a reader of the code, you'd have to do a two-pass visual scan
before you could begin to understand any of it. And you would have to
do that for *every* block, just in case, even if only 1% of them had a
variable defined later.

David

--
Rails training from David A. Black and Ruby Power and Light:
   Intro to Ruby on Rails January 12-15 Fort Lauderdale, FL
   Advancing with Rails January 19-22 Fort Lauderdale, FL *
   * Co-taught with Patrick Ewing!
See http://www.rubypal.com for details and updates!

Hi,

···

In message "Re: ruby1.9 block scope" on Tue, 30 Sep 2008 16:49:19 +0900, Mike Gold <mike.gold.4433@gmail.com> writes:

Making the scope of x contingent upon what comes later would result, I
believe, in extreme confusion.

One might argue that when 'x = 45' appears before bar and baz, this
_already_ changes the meaning of bar and baz. But the situation here is
entirely different, in my mind. Don't most of us read code from top to
bottom?

Understandable. That's the very reason the current Ruby does not work
like this.

              matz.

Mike Gold wrote:

Making the scope of x contingent upon what comes later would result, I believe, in extreme confusion.

Let's say Foo is a large class. Joe Schmo, who did not write Foo, comes along and adds some code to the bottom, such as the 'x = 45' in your example. Suddenly there is a bug in Foo. It seems impossible to Joe, but there it is. He wonders if it is caused by the recent sunspots. He wraps his computer in tin foil, but to no avail. The tests for bar and baz still fail as a result of his (obviously, to him) unrelated change.

This was the 'tall' case, but there is also the 'wide' case of deeply nested scopes. An equal helping of confusion applies here too.

One might argue that when 'x = 45' appears before bar and baz, this _already_ changes the meaning of bar and baz. But the situation here is entirely different, in my mind. Don't most of us read code from top to bottom?

Yes, I would argue that, and I believe most of us don't *add* new code always at the bottom of the file. If the bar and baz methods are defined at the bottom and Joe Schmo adds x = 45 at the top, he has the same problem. I really don't see how it's any different; it's symmetric. Bugs happen, and it's possible to come up with "problems cases" for absolutely every feature in ruby, but that doesn't mean they turn out to be problems in reality.

I must ask: is this confusing to *you* or are you trying to "protect" a hypothetical Joe Schmo? I'll take the hypothetically confused Joe Schmo over the very *real* confusion of every ruby newbie who wonders why his local var has disappeared after the loop.

···

--
Daniel

David A. Black wrote:

The reason I haven't introduced it yet in Ruby is that single
assignment after the blocks can change the scope of a variable
afterward. Same thing happens assignments _before_ the blocks
already. But I hesitated to enhance that far.

Please continue to hesitate :slight_smile: That would be very hard to deal with.
As a reader of the code, you'd have to do a two-pass visual scan
before you could begin to understand any of it. And you would have to
do that for *every* block, just in case, even if only 1% of them had a
variable defined later.

You dont need a two-pass visual scan; it just allows you to assume that a variable defined a line L of a method will be available for reference at line L+n, no matter if it was defined inside a block or not. It should be common sense, really.

···

On Tue, 30 Sep 2008, Yukihiro Matsumoto wrote:

--
Daniel

Yukihiro Matsumoto wrote:

Hi,

>Making the scope of x contingent upon what comes later would result, I
>believe, in extreme confusion.

>One might argue that when 'x = 45' appears before bar and baz, this
>_already_ changes the meaning of bar and baz. But the situation here is
>entirely different, in my mind. Don't most of us read code from top to
>bottom?

Understandable. That's the very reason the current Ruby does not work
like this.

              matz.

The current ruby doesn't, but a future one might? The reason I posted
was because the phrase "I haven't introduced it yet" might imply that it
could happen.

···

In message "Re: ruby1.9 block scope" > on Tue, 30 Sep 2008 16:49:19 +0900, Mike Gold > <mike.gold.4433@gmail.com> writes:

--
Posted via http://www.ruby-forum.com/\.