Ruby 1.9.1, The Stuff It Gives Us
We’re still kicking the Ruby hardcore. We’ve just been massively busy locked in the Kinetic Barn HQ this winter. Anyway, here is a list of the latest things we’ve found interesting about the first stable 1.9.x release of MRI Ruby.
Note: Some of these have been in the 1.9 branch for awhile, I’m just taking the moment to get you all acquainted.
Newlines allowed before ternary colon operator (:) and method call dot operator (.)
Before this you might note that you could do this in Ruby, and it was valid.
Person.
set_first_name('Ben').
capitalize.
to_a
# or...
dog = Person.first_name == 'Ben' ?
'Cookie' :
'pookie'You won’t see the former very often, but you can do it if you keep to coding standards of 80-100 columns of text in your source.
I’ve seen and used the latter numerous times, however I usually don’t put a newline after the colon. Eithercase, Ruby makes things a bit more clearer in 1.9 (though these are bad examples of their use cases).
Person
.set_first_name('Ben')
.capitalize
.to_a
# or...
dog = Person.first_name == 'Ben' ?
'Cookie'
: 'pookie'Kernel#methods and #singleton_methods used to return an array of strings but now they return an array of symbols.
I use this daily within Irb to see what methods are in my objects. You used to receive an Array of Strings, of all the methods on the object you ran this against. Now you will get this.
>> String.methods.sort
=> [:, :, :=>, :, :, :, :, :, :__id__, :__send__, :allocate, :ancestors, :autoload,
:autoload?, :class, :class_eval, :class_variable_defined?, :class_variables, :clone,
:const_defined?, :const_get, :const_missing, :const_set, :constants, :display,
:dup, :eql?, :equal?, :extend, :freeze, :frozen?, :hash, :id, :include?,
:included_modules, :inspect, :instance_eval, :instance_method,
:instance_methods, :instance_of?, :instance_variable_defined?,
:instance_variable_get, :instance_variable_set, :instance_variables, :is_a?,
:kind_of?, :method, :method_defined?, :methods, :module_eval, :name, :new,
:nil?, :object_id, :po, :poc, :pretty_inspect, :pretty_print, :pretty_print_cycle,
...]If you know anything about Ruby low level you might guess someone got smart and decided it was better to utilize the Symbol table instead of building these lists of anonymous String instances.
Hash; preserving item insertion order
Yes, Hashes are now ordered… which is pretty odd if you’ve been writing Ruby for awhile now. We all used to utilize Arrays, and I hope we still do. But Hashes are now ordered by the pattern in which you insert keys/values into them.
[1,2,3,4,5].inject({}) { |hash, value| hash["name_#{value}"] = value; hash }
# Ruby 1.8
=> {"name_4"=>4, "name_5"=>5, "name_1"=>1, "name_2"=>2, "name_3"=>3}
# Ruby 1.9
=> {"name_1"=>1, "name_2"=>2, "name_3"=>3, "name_4"=>4, "name_5"=>5}As a community, let’s not go nuts and start replacing our usage of Array’s with Hashes when we needed to persist order. I’m fairly certain the speed of an Array will always trump a Hash.
Named/Coroutine style Regexp
Dave Thomas can give you a better description than I can…
sentence = %r{
(?<subject> cat | dog | gerbil ){0}
(?<verb> eats | drinks| generates ){0}
(?<object> water | bones | PDFs ){0}
(?<adjective> big | small | smelly ){0}
(?<opt_adj> (\g<adjective>\s)? ){0}
The\s\g<opt_adj>\g<subject>\s\g<verb>\s\g<opt_adj>\g<object>
}x
md = sentence.match("The cat drinks water")
puts "The subject is #{md[:subject]} and the verb is #{md[:verb]}"Dir.exists?/.exist?
This one annoyed quite a few people, because before you had to do File.exists?(”/tmp”) to test the existance of a directory. Odd, but fixed.
Negative operators such as ”!”, ”!=” and ”!~” are now overloadable
OOOHHH… more fun for the DSL writers out there! dm-core, I’m looking at you! :)
Rake and RubyGems Made Core
Both Rake and Rubygems are now included in the core library. Hopefully it’s still as easy to upgrade them both!
Thats Not All
Of course this isn’t it, and the entire list is a great read. If anyone else has anything feel free to post… like the difference between proc and lambda now, new Hash key syntax {apple: 1, pear: 2} or anything else… feel free to comment.
The Rails Language aka The DHH DSL 10
Please Note: This is bitching. I’m a nit picky kinda programmer. I pull things apart, rip out what I hate and go nuts over it so I remember to never do it again. This is a rant, your warned.
I’m not too happy with a lot of things going into Rails lately, outside of the stuff that they are learning about through other frameworks. Some additions have been made to Rails lately that are bringing it further from Ruby, into its own language.
Many people already believe that “Ruby on Rails” is a language in and of itself. I guess they believe that the “Ruby on” part is just a cool name. Frankly, some commits as of late could possibly be developing that language.
Array#second, #third, etc.
When I first learned scripting languages I learned Python, and I still love Python (despite having no current use for it). Even back to my C/C++ days I enjoyed Array indexing as Array#[] (in ruby terms). Whats so hard about an integer (0..n) being used between them? How else do you easily modify them into Ranges…. well Rails has solved all of this for us!
Array#first, plus now Array#second, #third, #fourth. Our playboy even says he’s found a way of “massive savings in overhead” for something Ruby never had a need for in the FIRST place.
Object#try
Object#try is another one. Again, something Ruby and Matz never put into the language itself. That doesn’t stop Rails from developing it into its own language.
Object#blank?
Ever try to bring a script over from Rails, and find yourself rewriting #blank?. Sure, I love blank, it saves time right? But where’s the Ruby in a method that was never originally intended to be monkey patched into the language itself?
My Point
My point is, there are other frameworks that try to keep this sort of thing to a minimum. The benefits are countless, and I think the best are…
- Monkey patching is kept to a minimum. If you don’t understand the danger in monkey patching, please don’t ever read a blog entry I write again.
- Lowered need of detailed attention being required when transferring code to other frameworks and platforms
- Less lines of code within your code base, required pieces.
- Universal code that is understandable by anyone using the original language.
- Learning the appropriate methods the first time around
- Not having to re-implement if you find yourself without one of these methods
Now I’m not against these sorts of things completely, and there are frameworks that implement them correctly (Merb and DataMapper’s combined ExtLib library being one of them).
I’m just not impressed by the magic tricks anymore, and tired of seeing Rails core become the bastard child of someone’s personal “good ideas”. Just because your doing it in your projects doesn’t mean it should be forced down my throat.
