Local variables & blocks

was on rubygarden and had this idea regarding local and blocks :

in general, i like the way things work, but occansionally would like to be
able to ‘export’ a variable from inside a block. so, i think to myself, why
not an export keyword? something

(IO.readlines (path)).each do |line|
export max = 0

fields = line.split delim
max = [max, fields].max

end

puts max >> 42

what’dya think?

export would be a cross between C’s static modifier (declared/defined once
only), but would be ‘exported’ into the parent scope - lexical or dynamic i’m
not sure - but you get the picture…

the mnemonic is like that of the shell’s ‘export var=42’

-a

···

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

I like it. I’m forever defining a variable as nil outside a block so it
doesn’t get chewed by the change in scope. Perhaps it could work anywhere
there’s a new local scope - simply export it to the next higher scope…

Tim Bates

···

On Wed, 29 Jan 2003 04:34 pm, ahoward wrote:

what’dya think?


tim@bates.id.au

(IO.readlines (path)).each do |line|
export max = 0

fields = line.split delim
max = [max, fields].max

end

puts max >>> 42

what’dya think?

There’s obviously some support for this, but to me it’s unnecessary.
If I need to do code like that, I factor it into a method:

def find_max(…)
foo.bar.each do |quux|

return max # ← That, or …
end
return max # … that

max = find_max(…)

I like small methods, and code like you’ve presented is a visual cue
for me to refactor.

None of this means the idea is without merit, though.

Gavin

···

On Wednesday, January 29, 2003, 5:04:51 PM, ahoward wrote:

Hm, don’t know. I can see the benefits but personally I prefer it the other
way round: the calling scope stays in control. I am completely satisfied
with

max = 0

(IO.readlines (path)).each do |line|

fields = line.split delim
max = [max, fields].max

end

puts max >> 42

The difference is not too big and you achieve the same.

Apart from that: from a technical point of view, what does happen if you
create a Proc instance? Normally the variable binding is established at
creation time. Your feature requires to bind a variable dynamically each
time a block is used the first time in a certain context. I don’t know
whether this is feasible with the current interpreter implementation, but I
do guess that it’s a major change.

Regards

robert

“ahoward” ahoward@fsl.noaa.gov schrieb im Newsbeitrag
news:Pine.LNX.4.33.0301290535530.2139-100000@eli.fsl.noaa.gov

was on rubygarden and had this idea regarding local and blocks :

in general, i like the way things work, but occansionally would like to
be
able to ‘export’ a variable from inside a block. so, i think to myself,
why
not an export keyword? something

(IO.readlines (path)).each do |line|
export max = 0

fields = line.split delim
max = [max, fields].max

end

puts max >> 42

what’dya think?

export would be a cross between C’s static modifier (declared/defined
once
only), but would be ‘exported’ into the parent scope - lexical or dynamic
i’m

···

not sure - but you get the picture…

the mnemonic is like that of the shell’s ‘export var=42’

-a

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

(IO.readlines (path)).each do |line|
export max = 0

fields = line.split delim
max = [max, fields].max

end

puts max >>>> 42

what’dya think?

There’s obviously some support for this, but to me it’s unnecessary.
If I need to do code like that, I factor it into a method:

def find_max(…)
foo.bar.each do |quux|

return max # ← That, or …
end
return max # … that

max = find_max(…)

I like small methods, and code like you’ve presented is a visual cue
for me to refactor.

None of this means the idea is without merit, though…

<random_raving>
…especially since I used to think that Java was readable enough if
you keep the methods small. Then I realised that one method of Java
is often one line of Ruby, because of things like #map. This export
idea could be another good progression to reduce unnecessary
methods.
</random_raving>

Could this be made a solution to the block parameter scoping problem?
(I don’t remember any concrete decision on that.) That is, make all
parameters local, and then use “export” to export the one(s) you want
to be visible from outside?

b = 5
foo { |b| … }
b # → 5

x = -9
bar do |x|
export x

end
x # → something else, set within ‘bar’

Since the latter code is rarely needed, this seems like a good
solution to me.

Gavin

···

On Wednesday, January 29, 2003, 6:17:44 PM, Gavin wrote:

On Wednesday, January 29, 2003, 5:04:51 PM, ahoward wrote:

Could this be made a solution to the block parameter scoping problem?
(I don’t remember any concrete decision on that.) That is, make all

matz has already explained his plans on this [52440].
They might change, though.

parameters local, and then use “export” to export the one(s) you want
to be visible from outside?

To summarize:
‘=’ refers to variables in the current method / class scope.
‘:=’ refers to local vars
block arguments are assigned with ‘:=’
in case of shadowing a warning is issued.

···

On Wed, Jan 29, 2003 at 04:40:21PM +0900, Gavin Sinclair wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Not only Guinness - Linux is good for you, too.
– Banzai on IRC

elimnating methods is very important to keep things fast too, not just to
keep them readable.

-a

···

On Wed, 29 Jan 2003, Gavin Sinclair wrote:

<random_raving>
…especially since I used to think that Java was readable enough if
you keep the methods small. Then I realised that one method of Java
is often one line of Ruby, because of things like #map. This export
idea could be another good progression to reduce unnecessary
methods.
</random_raving>

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

Hi,

···

In message “Re: Local variables & blocks” on 03/01/29, Mauricio Fernández batsman.geo@yahoo.com writes:

To summarize:
‘=’ refers to variables in the current method / class scope.
‘:=’ refers to local vars
block arguments are assigned with ‘:=’
in case of shadowing a warning is issued.

I may drop ‘:=’ part, i.e.

  • block parameters are local to the block

  • shadowing cause warnings

  • no other way to make block local variables

    					matz.
    

From what I’ve seen, the Ruby Way to make things fast seems to be to
rewrite it in C. The C compiler can do inlining that the Ruby
interpreter cannot.

Paul

···

On Thu, Jan 30, 2003 at 12:46:27AM +0900, ahoward wrote:

elimnating methods is very important to keep things fast too, not just to
keep them readable.

To summarize:
‘=’ refers to variables in the current method / class scope.
‘:=’ refers to local vars
block arguments are assigned with ‘:=’
in case of shadowing a warning is issued.

I may drop ‘:=’ part, i.e.

  • block parameters are local to the block
  • shadowing cause warnings
  • no other way to make block local variables

so, correct me if i am wrong, but this does not address the need to do

x = nil
a.each do |item|
x = …
end
p x

does it?

it seems like only

  • shadowing cause warnings

is different from current behavior right?

would this somehow allow this type of behavior

loop { export x; x = … }
p x

which would be exactly the same as

x = nil
loop { x = … }
p x

??

-a

···

On Thu, 30 Jan 2003, Yukihiro Matsumoto wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

Given this, then:

def foo(&block); block.call; end
p = proc { p x }
foo { x = 1 }
p.call()

Will print:

1

but currently gets:

NameError: undefined local variable or method x' for #<Object:0x4028cce0> from (irb):2 from (irb):2:in call’
from (irb):4

should it instead issue a warning, since the code is not
backward-compatible?

Paul

···

On Thu, Jan 30, 2003 at 01:09:19AM +0900, Yukihiro Matsumoto wrote:

I may drop ‘:=’ part, i.e.

  • block parameters are local to the block
  • shadowing cause warnings
  • no other way to make block local variables

you are obviously correct. however, i wrote a decoder recently which decoded
some largish text weather data. it took around 30 seconds to run - which was
actually acceptable. i decided to profile it, in 5 minutes i changed two
offending lines, and now it runs in under 1 sec. my c++ version takes 3
seconds. i think profiling is key with languages like ruby and perl.

-a

···

On Thu, 30 Jan 2003, Paul Brannan wrote:

On Thu, Jan 30, 2003 at 12:46:27AM +0900, ahoward wrote:

elimnating methods is very important to keep things fast too, not just to
keep them readable.

From what I’ve seen, the Ruby Way to make things fast seems to be to
rewrite it in C. The C compiler can do inlining that the Ruby
interpreter cannot.

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

I like this - I find myself defining a variable simply so that it’ll
persist beyond the end of a block fairly often, and it’s always struck
me as a bit of a code smell.

martin

···

Yukihiro Matsumoto matz@ruby-lang.org wrote:

I may drop ‘:=’ part, i.e.

  • block parameters are local to the block
  • shadowing cause warnings
  • no other way to make block local variables

Just to make sure: From what I read in this thread there are quite some
situations which could be problematic with exporting a variable from a
block to its enclosing scope. Are all these situations properly regarded?

I still feel a unwary about this change…

Regards

robert

“Yukihiro Matsumoto” matz@ruby-lang.org schrieb im Newsbeitrag
news:1043856555.207520.16066.nullmailer@picachu.netlab.jp…

···

Hi,

In message “Re: Local variables & blocks” > on 03/01/29, Mauricio Fernández batsman.geo@yahoo.com writes:

To summarize:
‘=’ refers to variables in the current method / class scope.
‘:=’ refers to local vars
block arguments are assigned with ‘:=’
in case of shadowing a warning is issued.

I may drop ‘:=’ part, i.e.

  • block parameters are local to the block
  • shadowing cause warnings
  • no other way to make block local variables

matz.

Hi,

  • block parameters are local to the block
  • shadowing cause warnings
  • no other way to make block local variables

Given this, then:

def foo(&block); block.call; end
p = proc { p x }
foo { x = 1 }
p.call()

Will print:

1

No. The role of idenfiers are fixed at compile time by appearance
order. Since “x” in “proc{p x}” appears before assignment, it’s not a
local variable access in any way. So behavior of this chunk of code
will not be changed. But yes, there’re some incompatible cases, and I
will prepare warnings for these cases in the future stable-before-Rite
version.

						matz.
···

In message “Re: Local variables & blocks” on 03/01/30, Paul Brannan pbrannan@atdesk.com writes:

I’m curious what were the offending lines and how did you changed them?

···

On Thursday, 30 January 2003 at 2:27:11 +0900, ahoward wrote:

On Thu, 30 Jan 2003, Paul Brannan wrote:

you are obviously correct. however, i wrote a decoder recently which decoded
some largish text weather data. it took around 30 seconds to run - which was
actually acceptable. i decided to profile it, in 5 minutes i changed two
offending lines, and now it runs in under 1 sec. my c++ version takes 3
seconds. i think profiling is key with languages like ruby and perl.


Jim Freeze

Think big. Pollute the Mississippi.

Hi,

I may drop ‘:=’ part, i.e.

  • block parameters are local to the block
  • shadowing cause warnings
  • no other way to make block local variables

so, correct me if i am wrong, but this does not address the need to do

x = nil
a.each do |item|
x = …
end
p x

does it?

It does. The key is:

  • no other way to make block local variables

So that x in

a.each do |item|
x = …
end
p x

would not be a block local variable. The code above will work without
preceding “nil” assignment.

						matz.
···

In message “Re: Local variables & blocks” on 03/01/30, ahoward ahoward@fsl.noaa.gov writes:

elimnating methods is very important to keep things fast too, not just
to keep them readable.

From what I’ve seen, the Ruby Way to make things fast seems to be to
rewrite it in C. The C compiler can do inlining that the Ruby
interpreter cannot.

you are obviously correct. however, i wrote a decoder recently which decoded
some largish text weather data. it took around 30 seconds to run - which was
actually acceptable. i decided to profile it, in 5 minutes i changed two
offending lines, and now it runs in under 1 sec. my c++ version takes 3
seconds. i think profiling is key with languages like ruby and perl.

-a

Profiling is important in any language. Have you profiled your C++ code? I’ll
bet there’s an offending line or two in there as well.

···

On Thu, 30 Jan 2003 02:27:11 +0900 ahoward ahoward@fsl.noaa.gov wrote:

On Thu, 30 Jan 2003, Paul Brannan wrote:

On Thu, Jan 30, 2003 at 12:46:27AM +0900, ahoward wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================


“Daniel P. Zepeda” <daniel@z,e,p,e,d,a,-,z,o,n,e.net>
(Remove commas for address)

Quote 1:

so, correct me if i am wrong, but this does not address the need to do

x = nil
a.each do |item|
x = …
end
p x

Quote 2:

loop { export x; x = … }
p x

Quote 3:

x = nil
loop { x = … }
p x

OK, this may seem an odd set of quotes, but I have a question. What
happens when you do this:

def munge(a)
a.each {
> i |
export x;
x = x + i
}

  p x

end

…and ‘a’ is empty? ‘x’ never happens.

Now, you say that Quote 2 would be exactly identical to Quote 3, but
it seems to me that it would be largely painful to search through
scopes to make sure you catch all initializations:

def quux()
proc {
export x;

     proc {
        export y;

        proc {
           export z;
        }
     }
  }

end

First of course is the question which scope each fall into (you said
“local” scope so I assume #quux-wide), and then you’d have to make
ruby hunt through all your blocks. Then what happens if you pass one
as a parameter… where do exports go then? :wink:

Plus, there’s the most important consideration:

x = nil
export x
^— One extra character to type!

:wink:

···

On Thu, 30 Jan 2003 01:46:54 +0900 ahoward ahoward@fsl.noaa.gov wrote:


Ryan Pavlik rpav@users.sf.net

“Ha! Who needs wits when you’ve got swords!” - 8BT

Hi,

···

In message “Re: Local variables & blocks” on 03/01/30, “Robert Klemme” bob.news@gmx.net writes:

Just to make sure: From what I read in this thread there are quite some
situations which could be problematic with exporting a variable from a
block to its enclosing scope. Are all these situations properly regarded?

I still feel a unwary about this change…

Describe your feeling and ideas. This is why I post. What kind of
situations do you think this change does not cover properly?

						matz.