What's to Like in Ruby 1.9
9:52 AM EDT Tuesday, April 29 2008
A few days ago, Charles Nutter asserted that "people are not flocking to Ruby 1.9 in droves". I would consider myself one of those people. When I thought about Ruby 1.9, I just assumed they were tweaking the syntax a little but mostly working on a VM that would make Ruby faster. Mainly though, Ruby 1.9 is an unstable, development release, so it's really just for playing around with it. The intent is for 1.9 to drive development for Ruby 2.0, and have people flock to Ruby 2.0 once that is ready for prime time.
Another factor is that up until today, I didn't really know much about what is planning on being added to Ruby 1.9. There is a complete list of changes in Ruby 1.9, but it wasn't until I came across a slideshow by Bruce Williams that covers some of the changes in Ruby 1.9 that I took the time to download, install and try out a few new features. So I thought I would put together a blog entry of 5 of my favorite changes:
New Literal Syntax for Hashes
{:foo => 1, :bar => "two"}now becomes{foo: 1, bar: "two"}. This is probably minor, but I really like it. It's a little bit cleaner, although I'm sure Obie will be sad to see the hash rocket go. Actually, I'm sure the hash rocket will still be supported, it will just become no longer idiomatic.New Proc literal
But fear not Obie, we lose one operator, the hash rocket, but gain another, the proc rocket. You can now define a proc like this:
double = ->(x) { x * 2 } puts double.(5) # => 10That can lead to some pretty crazy things, like this:
p = ->(n, name="it", &block) { n.times{|i| block.call } puts "I did #{it} #{n} times" } p.(3) do |i| puts "#{i} is #{i.even? ? 'not ': ''}odd" end p.(3, "foo") do |i| puts "#{i} is #{i.even? ? 'not ': ''}odd" endThe difference being that you can now have default values for arguments to a Proc and also you can pass a Block to a Proc. I could see this being used in metaprogramming. You could probably do a lot of things with this instead of things that get done using class_eval now.
#Ruby 1.8 class Foo end Foo.class_eval <<-CODE def bar(x,y=2) puts "x => \#{x}, y => \#{y}" end CODE #Ruby 1.9 class Foo end Foo.send(:define_method, :bar, ->(x, y=2) { puts "x => #{x}, y => #{y}" })Not sure yet if that would be better, I guess we'll see.
Hashes preserve insert order
Say goodbye to using 2D arrays just because you want things to be in a certain order. This is very convenient, but I was always under the impression that this is the way it was for performance reasons. I'd like to hear more about this. Is this one of those things where 80% of the time you don't care about that level of performance because your hash is relatively small and the convenience of preserving sort order is a better benefit? Is there some kind of
FastHashclass that can be used for cases where you don't care about ordering and better performance is needed? Or is the performance of the insertion-order Hash good enough for all cases?New Regular Expression Engine
The Oniguruma regular expression engine is used in Ruby 1.9. This engine supports many advanced regular expression features. I once looked into directly porting the Perl Markdown code into Ruby but quickly found out that wasn't possible given the limitations of the Ruby 1.8 regular expression engine, so it's nice to see Ruby will have a regular expression engine that is on par with that of any other language.
Object#tap and Symbol#to_proc
I lumped these together into one because they are both kind of the same thing. These are two language level features that have become idiomatic Ruby because they have been added in Rails. The downside has been that if you are not in Rails, you either don't have these, or you have to define them to use them. Now that is a problem no more and they are just going to be part of Ruby.
Symbol#to_procyou should recognize andObject#tapis the same thing asreturning.