evan_tech

Previous Entry Share Next Entry
08:46 pm, 10 Aug 03

ruby 1.8, loop variables

Overview of the changes in Ruby 1.8, which has been in development since 2001. (There's also a link there to a summary of the changelog.)

Bunch of neat stuff in there, and a bit of weirdness. I’m just reading it, so I’ll reserve my comments. It looks like it’s mostly cleanups and importations from other languages, but that persons.sort_by bit is neat! And REXML is really nice, especially when you’ve dealt with other XML libraries before.

But I will add this: One thing in particular I think they wanted to fix is the block scoping. (It looks like they haven't?)
I was just talking to Brad about this, so I’ll tell you, too.
Basically the problem is specifying the scope of a variable that is defined as part of a control structure. The C++-ism is this:
for (int i = ...) {
    // ...
}
// is i still defined here?

Officially, I think the answer is no. But Microsoft’s compiler (at some point, maybe not anymore) kept i around, so it’s never been too clear. (Microsoft didn’t necessarily make a mistake; it’s possible the specs were unclear or changed. If y’all know anything about this, I’d love to learn.) In any case, this isn’t such an annoying problem in C++, unless you have a sequence of for loops that all want to use i, and even then you can just pull the declaration of i out to the top and you won’t have problems.

It’s worse in a languages that don't let you "declare" variables, because (depending on their semantics) it means it can be possible to have code that creates a variable no matter what. Add that to a language that allows code to run in the global namespace and you get this problem (discovered in the Python startup code in /etc):
for m in ...:
    # do some stuff with m
del m

Ew. They repeat that sort of structure for each loop in the code there so they don’t pollute.


Ruby has traditionally had the same problem, and it’s even worse with Ruby because everything is written as blocks.
3.times do |i|
    # ...
end

At this point, do we still have i? Should we?
(Answer in ruby: no, it's gone.)
If i was declared outside of this loop, did we just clobber it?
(Ruby: yes, i think. And there’s no way to avoid this without renaming i, which sucks.


For what it’s worth, my brief test with Perl indicates that the loop variable (even if it wasn’t my’d or anything) gets local scope for the block, so it neither clobbers existing variables nor persists afterwards...