Ruby 1.8.0 Released
waieitch writes "A long-waited new version of the scripting language, Ruby 1.8.0 has just been released. You can download from here, and the changelog is available. With many new libraries, say dRuby, ERB, REXML, this version is doubled by 1.6.8 in size."
I thought that code blocks were a pretty lame excuse for proper functions-as-data, so I'm a little bit surprised to see them mentioned as a great feature. Did I miss something?
You did.
Code blocks are probably one of the most important features of Ruby that differentiates it from Python.
From what I understand, code blocks are basically anonymous functions that the method they are passed to can only invoke with yield, right?
wrong.
Or is it possible to treat them as any other parameter, i.e. store them, pass them further around, take more than one etc?
Yes. Yes. Yes. Yes (well, that last one is a qualified yes, if I understand your question correctly: you have to convert them to Proc objects before you can pass more than one of them to another method due to the fact that the '&' block delimiter in the method's parameter list can only be on the last parameter - it's not a big limitation).
At first glance, code blocks don't seem that interesting, cool or useful, however, I was able to create a domain-specific hardware description language using them without the need to create any parser for that langauge. It was written in pure Ruby, but to the user it looks like another language in it's own right.
So I could do things like (if you're familiar with VHDL this should look familiar):
process(clk,rst) {
if clk.event and clk == '1'
counter.assign counter + 1
elsif rst == '1'
#do resest:
counter.assign 0
end
}
#
It's all written in pure Ruby. The part between the '{' and '}' is a code block that's being passed to the process method which will execute the block whenever the value of clk or rst changes. So essentially, code blocks allowed me to make Ruby look a lot like VHDL. It looks very natural. AFAIK, this sort of thing is not (easily) doable in Python.
Why can't I define a method that takes two or more blocks (e.g. if/then/else) with the same syntax I use for methods that take a single block? Why can't I introspect the structure of a block? Why the duality with Proc objects? In short, why aren't blocks first class objects?
To clarify this first: It's always possible to create multiple Proc objects with Proc.new, lambda or proc and pass them to a method.
There are two reasons why there are blocks AND Proc objects:
It would perhaps be possible to have something like that:
But there is an ambiguity because the first block could also be a hash constructor. I am not sure if it would be possible to solve that problem by changing the parser. You could limit yourself to use only doBTW: The if/then/else is not a method call and the selectors consist only of a single word in Ruby unlike in Smalltalk. So it would require a big change to the language and the interpreter if blocks should be used there.
Introspection of blocks is a good idea. Perhaps this will be possible if the new VM for Ruby 2.0, called Rite, is implemented. AFAIK it also should be possible to change code in the parse tree on the fly at arbitrary places then.
More to the point, in ruby I'd like to be able to change the scope or storage class of an object reference without having to rename it.
This is clearly a tradeoff. You can choose between having to look up the variables everytime you want to know their scope or between seeing it easily and change every variable if you want to extract a method. I think to choose the latter is a good choice for a language where you don't usually program in a code browser.
You know, reading over the the information available for Perl 6, I get the idea that a lot of the improvements intended for Perl 6 were actually stolen from Ruby. As much as I love Perl, the OO implementation is a bolted-on, pain-in-the-ass kludge. Ruby's is an integral part of the language, and Ruby is a very nice language.