Programming with Ruby (NFJS)
Posted on December 05, 2004 by Scott Leberknight
It's been a month since I went to the Reston No Fluff Just Stuff and I still haven't written all the sessions. Maybe next time I'll blog the sessions while I'm there. Anyway, went to a good session given by Dave Thomas on the Ruby programming language. It seems there has been a lot of discussion lately by Stu Halloway, Dave Thomas, and others about metaprogramming and how certain languages don't need the notion of patterns simply because the language supports the "patterns" as part of the language.
Some of the cooler things Ruby supports include closures, blocks, iterators, mixins, and the ability to add and remove methods dynamically from core classes like String. In Ruby, everything is an object, unlike Java and C# which have primitive and reference types. And Ruby does away with the special new
keyword in favor of a special initialize
method which is invoked when you call new
to create an object:
myBook = Book.new("Programming Ruby")
Another cool thing is that Ruby provides native support for defining attributes and specifying whether they are readable and/or writeable using a shortcut notation:
attr_reader :title
attr_accessor :artist
The above defines a read-only attribute named title and a read/write attribute named artist. Even better you can directly access these attributes using dot notation, e.g. myBook.title
and myBook.artist = "Dave Thomas"
without needing to declare mundane Java-style getters and setters. The above are shorthand for a def
block which is the formal notation for defining attributes. For example, the attr_accessor
is equivalent to the following:
def artist
@artist
end
def artist=(val)
@artist = val
end
In Ruby, instance variables are always private and are prefixed with an @ symbol, e.g. @artist
. That's kinda cool. No more project code convention arguments whether instance variables should be prefixed with an underscore, or always prefixed by the this
keyword, or any other contrived mechanism for unambiguously identifying instance variables in code.
Ruby support for blocks and iterators is really cool. For example, since everything is an object, you can write code like the following:
3.times { puts "Hello, Ruby" }
myHash.each { |key, value|
puts "#{key} -> # {value}"
}
IO.foreach("/my/file") do |line|
process(line)
end
The first line in the examples above prints "Hello, Ruby" three times, as you would expect. Pretty nice. The next example shows iterating over a hash and printing the keys and values. The last example shows iterating over the lines in a file and calling some method process
to handle each line. In Ruby a block is simply a "chunk" of code attached to a method. This has the nice side effect that you can pass around blocks of code to be executed in predefined methods. So you could define a method called do_twice
and define it as such:
def do_twice
yield
yield
end
Then if you called the do_twice
method using the line do_twice { puts "Ruby is cool!" }
, the output would simply be "Ruby is cool!" printed twice.
There was a lot more to Dave's presentation including examples of scraping a web page, connection to a database, and information on Ruby web and persistence frameworks. All in all, Ruby seems like a pretty cool language, and I'd like to try it out on a few projects. Oh wait, I just remembered that requires having some free time...
Check out Dave's Programming Ruby book.