ruby scoping
Mood: confused
Posted on 2006-04-18 09:41:00
Tags: ruby weight programming
Words: 218

I weighed in this morning, and I'm at my lowest weight since starting to track it (oddly enough, despite eating many tasty cookies and candy on Sunday). Hooray!

On a completely separate note, I'm learning Ruby to use in my next project. It seems like a nice language, but I have a complaint already. Consider the following code:

[1,2,3].each {|e| print e, " " }

This prints out "1 2 3 " - the each operator iterates over the elements of the array, and the block that follows it ({|e| print e, " " }) operates on each one of them. So that's fine, and e is undefined after the block executes, as I would expect.

What I don't like is that the following code:
e = 10
[1,2,3].each {|e| print e, " " }
print e

prints out "1 2 3 3" - the e argument to the block ends up overwriting the e variable declared outside the block! This seems like a big violation of scoping - shouldn't the e inside the block be unrelated to the e outside the block? Can anyone (omega697, perhaps) explain this to me?

I mean, I can see why it might be useful (if you want to save the last value that the block executed on), but the penalty of possibly overwriting a variable outside the block's scope seems a bit much to handle...


Comment from omega697:

This behavior is scheduled to be changed in the next major stable release of Ruby, such that the value of e will still be 10.

According to Matz, this is the "most regrettable behavior in Ruby."

That said, this code:

a = 5
10.times do a += 1 end

Will still leave 15 in the value of a. Block parameters (like e in your example above) will be block-local. But the block will still have access to the other variables outside, because blocks in Ruby are closures and store their environment so that when the code executes, it executes in that environment.

Also, on a minor, but important technicality, each is a method and not an operator :o)

If you have any more questions, let me know.

Comment from gregstoll:

Hey, that's great! (right, I would expect the block to act like a closure) Glad to see my instincts were "right" on this one.

Thanks a lot!

Comment from wildrice13:

Ouch. That goes against my sensibilities as well. Interested to see if somebody has an explanation...

Comment from sanjeev87:

Yeah, that certainly seems wrong. Glad to hear it will be fixed. Is this problem in the language spec, or the implementation? Since it's GPL, is there a difference? ;)

Comment from omega697:

It's not a bug in the implementation. It's part of the current language spec, which is being changed.

Comment from tehfanboi:

Congrats on the weightloss. Beyond that I don't understand a thing you are talking about and basically didn't read it.

Comment from gregstoll:

Heh, thanks! My BMI is down to 29.1, which isn't great, but it's a good start...(started at 29.6)

Comment from omega697:

BMI is a bunch of crap. Even if I lost 50 pounds, I would still be overweight according to BMI.

Comment from medryn:

It is hard to believe that Arnold Schwarzenegger is obese... (BMI 31)

Comment from onefishclappin:

omega697 is right that BMI isn't the end all be all, but it is a decent "guess" as to one's "fatness". IIRC, it's the 1st line of judging in the military if a person is fat. If they are "fat" by BMI, then they are allowed a waist (or hip for women) vs neck measurement. Basically allowing for dense people who have unnaturally inflated BMI's, but are in good shape. Of course, that's not a great measurement either, but you can do both with a scale & tape measure & an enlisted man. Good for you, none the less, on the weight loss! Buy yourself a CD or something to celebrate!

This backup was done by LJBackup.