Microsoft’s IronRuby project brings a powerful and fun dynamic language to the Windows platform.

In this article, I’ll examine the history of Ruby and the IronRuby project at Microsoft. I’ll talk about why a .NET programmer may want to learn and use Ruby, and cover the core syntax of the language to get you started learning it.

A Brief Introduction

The Ruby programming language is a modern, object-oriented scripting language, with a syntax inspired by languages like Perl and Smalltalk. It was conceived by Yukihiro Matsumoto (aka “Matz”). In his words, Matz wanted a language which was “more powerful than Perl and more object-oriented than Python” (for more from Matz, go to http://www.linuxdevcenter.com/pub/a/linux/2001/11/29/ruby.html). The language is designed to feel natural; something Matz calls the “principle of least surprise”. Version 1.0 of the language was released in 1996.

For several years, Ruby existed as a little-known scripting language that excelled in the tasks for which it was originally designed: manipulating data and environment with the least amount of effort. When I first started toying with it a few years ago, I was looking for something to replace batch files for automating some of my more common administrative tasks.

Ruby’s popularity really began to pick up when a small software company from Chicago, Illinois, named 37signals released a Web application framework named Rails. This new framework combined proven patterns like Model-View-Controller and ActiveRecord with new ideas like “convention over configuration”. The end result is a framework that achieves a lot with almost no code.

RubyCLR and IronRuby

In early 2006, John Lam went public with a project named RubyCLR, which worked as a bridge between Ruby and .NET. It allowed the user to have direct access to the richness of the .NET platform from Ruby, and even expose Ruby objects to the CLR. This project was very ambitious, but it wasn’t about putting Ruby on .NET so much as it was about letting the two worlds talk to each other. You still needed the Ruby runtime to be installed on your machine.

The RubyCLR project was a tremendous first step in understanding how to get Ruby and .NET to live together in harmony. John’s work did not go unnoticed, and in the end of 2006, he announced on his weblog that he would be joining Microsoft’s newly formed Dynamic Language Runtime (DLR) team. Just a few months before John’s announcement, Microsoft released version 1.0 of IronPython, a new implementation of the Python language on the .NET Framework. The Dynamic Language Runtime work takes the work done on IronPython and builds a runtime on top of the .NET Framework to allow dynamic languages to be brought onto .NET with much less effort.

John and his team announced IronRuby at the MIX conference in 2007. Perhaps more surprising than the revelation of the IronRuby project itself was that it would be the first truly open source .NET language from Microsoft. Not only would the source code be available, but outside contributions from the community are also accepted.

IronRuby is still a work in progress. Although drops have occasionally been available, usually in the context of another project (like the recently released Silverlight 2.0 Beta 2), those who are following the project are keeping up with the source tree and participating in the mailing lists.

Why Learn Ruby?

One of my favorite books, The Pragmatic Programmer: From Journeyman to Master (Andrew Hunt and David Thomas, Addison-Wesley Professional), encourages you to learn a new language every year. For me, the language that most changed my world-view when I learned it was Ruby.

Ruby is a fully object-oriented language in the Smalltalk sense. That means everything you interact with in the system is an object, including direct values like numbers. Even classes, which form the templates from which new object instances are created, are themselves objects in the system.

Because Ruby is a dynamic language, you’ll find that types become much less important. When a method takes an object as a parameter, there is no specification of what type that object needs to be. In fact, there is no compiler, so you might not discover until runtime that the object you passed to a method wasn’t for the requirements of that method.

If you’re like I was a few years ago, you might find this concept a little unsettling. Aren’t compilers here to provide help to you, so you can know these things as soon as possible before they cause runtime errors? The answer is, of course, yes: compilers do provide better feedback, sooner. So why should you throw them away and use a language like Ruby?

As it turns out, compilers are a very seductive form of straitjacket. The ability of compilers to tell you about mismatched types necessarily causes a form of type-rigidity. When you write a method, you may wish to say “objects here must be able to do ‘foo’ and ‘bar’”, and as such invent an interface called IFooBar. It seems like a neat solution to describing the requirements, but it fails you when you want to use someone else’s classes (especially those from the framework) that were written before IFooBar existed.

Ruby by Example

The best way to learn a language like Ruby is by exploring it interactively. Many dynamic languages have interactive prompts known as a REPL: Read-Execute-Print Loop. The REPL program for Ruby is called “irb” (which standards for “interactive Ruby”).

When you execute the “irb” program, you will be presented with an irb prompt:

C:\Users\Brad> irb
irb(main):001:0>

You type commands into the irb prompt and they are evaluated by the Ruby interpreter, with the results printed to your screen. REPLs like irb are an excellent way to learn a language: one statement at a time.

As an introduction to irb, convince Ruby to add two numbers. At the irb prompt, type “5 + 2” (without the quotes) and press Enter:

irb(main):001:0> 5 + 2
=> 7

The “irb(main):001:0>” part is the prompt that irb gave you. When you typed 5 + 2 and pressed Enter, irb printed the result to you as “=> 7”. The => is your hint that irb is showing you the result of the evaluation.

If Ruby believes you haven’t finished your expression, it will allow you to continue. For example, if you were to type “5 + 2 +” and press enter, Ruby realizes that you’re still missing part of the expression and allows you to finish:

irb(main):002:0> 5 + 2 +
irb(main):003:0* 13
=> 20

The second prompt line ends with “*” instead of “>” to let you know that you’re still finishing a previous statement.

Without further ado, I’ll jump into helping you learn Ruby interactively.

Basic Types

A programming language wouldn’t really be worth much if it couldn’t manipulate numbers. Simple arithmetic is no trouble for Ruby:

irb(main):004:0> 3 + 4
=> 7
irb(main):005:0> 3 * 4
=> 12
irb(main):006:0> 3 - 4
=> -1
irb(main):007:0> 3 / 4
=> 0
irb(main):008:0> 3.0 / 4.0
=> 0.75
irb(main):009:0> 0xF
=> 15
irb(main):010:0> 0x3 * 0xA
=> 30

As you can see, Ruby has support for integer and floating point types, and even accepts the common format for hexadecimal integers, although the result was of 0x3 * 0xA was printed in decimal (30 rather than 0x1E).

As with .NET, numbers are actually objects, so you can call methods on them:

irb(main):011:0> 14.to_s
=> "14"

Don’t try that with C++.

To to_s method converts an object into a string, so calling 14.to_s returns the string “14”. As with .NET’s ToString(), the to_s method is actually a method on Object, so you can convert everything in Ruby to a string.

Ruby’s strings have the full complement of operations that you might expect:

irb(main):012:0> "hello" + "there"
=> "hellothere"
irb(main):013:0> "Reader".length
=> 6
irb(main):014:0> "Reader".reverse
=> "redaeR"
irb(main):015:0> "reader".capitalize
=> "Reader"
irb(main):016:0> "Reader".include?("foo")
=> false
irb(main):017:0> "Reader".include?("ade")
=> true
irb(main):018:0> " Reader ".strip
=> "Reader"
irb(main):019:0> "Reader".gsub("e", "f")
=> "Rfadfr"
irb(main):020:0> "Reader".delete("ea")
=> "Rdr"
irb(main):021:0> "a" < "b"
=> true

There are several string operations available that you’re probably not used to. Testing if a string is between two other strings, alphabetically:

irb(main):022:0> "Bob".between? "Adam", "Chris"
=> true

The multiplication operator causes a string to repeat the given number of times:

irb(main):023:0> "hi" * 5
=> "hihihihihi"

The crypt method provides a salted one-way hash of the given string, useful for storing sensitive data like passwords:

irb(main):024:0> "Reader".crypt("ab")
=> "abofgDjq6JNJo"

Ruby doesn’t have a built-in character type. Characters are represented as numeric values, and character constants can be represented with the ? syntax. You can use the chr method to convert a number into the string equivalent of its character:

irb(main):025:0> "Reader"[2]
=> 97
irb(main):026:0> ?a
=> 97
irb(main):027:0> 97.chr
=> "a"

It’s not really helpful to just perform operations unless you can store the results for later use:

irb(main):028:0> x = 42
=> 42

Strings have a special syntax which allows embedded evaluation. This evaluation isn’t limited to just simple variable replacement, either: it’s a full evaluation:

irb(main):029:0> "The answer is #{x}!"
=> "The answer is 42!"
irb(main):030:0> "The answer is #{6 * 7}!"
=> "The answer is 42!"

You can avoid the evaluation by surrounding your string with single quotes instead of double quotes:

irb(main):031:0> 'The answer is #{x}!'
=> "The answer is \#{x}!"

Arrays in Ruby work much like the ArrayList class from .NET 1.0. They are variable-sized arrays which can store any type of data, indexed starting with 0:

irb(main):032:0> a = ["hello", 42, "world"]
=> ["hello", 42, "world"]
irb(main):033:0> a << 5.0 * 7.5
=> ["hello", 42, "world", 37.5]
irb(main):034:0> a[0]
=> "hello"
irb(main):035:0> a[6] = 'hi' * 2
=> "hihi"
irb(main):036:0> a
=> ["hello", 42, "world", 37.5, nil, nil, "hihi"]
irb(main):037:0> a[99]
=> nil

You can see the use of the push operator << to add items to the end of the array, and the use of the index operator [] to both get and set values. When you added an item past the end of the array, it filled in the holes in the array with nil values. When you access values beyond the end of the array, Ruby will return nil rather than throwing an exception.

You can slice off part of the array by using a ranged index. You can also combine this with the ability to use negative indices to access the array from the back rather than the front (where -1 is the last item, -2 is the second to last item, etc.). Although you can’t use reverse ranges to get reversed slices, you can use a forward range, and then call the reverse method afterward:

irb(main):038:0> a[-1]
=> "hihi"
irb(main):039:0> a[1..3]
=> [42, "world", 37.5]
irb(main):040:0> a[2..-2]
=> ["world", 37.5, nil, nil]
irb(main):041:0> a[-4..-1]
=> [37.5, nil, nil, "hihi"]
irb(main):042:0> a[-1..-4] # Won’t work
=> []
irb(main):043:0> a[-4..-1].reverse # Works fine
=> ["hihi", nil, nil, 37.5]

Like strings, you’ll find several unique and useful methods available to arrays:

irb(main):044:0> a
=> ["hello", 42, "world", 37.5, nil, nil, "hihi"]
irb(main):045:0> a.compact
=> ["hello", 42, "world", 37.5, "hihi"]
irb(main):046:0> a.join
=> "hello42world37.5hihi"
irb(main):047:0> [10, 75, 6, 29].sort
=> [6, 10, 29, 75]
irb(main):048:0> [[1, 2, 3], [4, 5, 6]]
=> [[1, 2, 3], [4, 5, 6]]
irb(main):049:0> [[1, 2, 3], [4, 5, 6]].flatten
=> [1, 2, 3, 4, 5, 6]

The final core data structure in Ruby is the Hash, similar to .NET 1.0’s Hashtable. It is an associative array, where the indices (keys) can be any kind of value, and the data they point to (values) can also be any kind of data. In practice, most Hashes use symbols for keys (see the sidebar, Symbols).

You declare hashes using the {} syntax, and you declare initialization values in “key => value” form. You can use the index operators to both get and set values in the hash:

irb(main):050:0> h = {:foo=>'bar', :baz=>'biff'}
=> {:foo=>"bar", :baz=>"biff"}
irb(main):051:0> h[:foo]
=> "bar"
irb(main):052:0> h[:unknown]
=> nil
irb(main):053:0> h[:baz] = "new"
=> "new"
=> {:foo=>"bar", :baz=>"new"}
irb(main):054:0> h.entries
=> [[:foo, "bar"], [:baz, "new"]]

Blocks and Closures

Although there were things like event handlers in .NET 1.x, you were forced to define full methods to attach to events when you wanted them handled. This led to the creation of a lot of methods that really only existed because the framework demanded it.

.NET 2.0 introduced the concept of anonymous delegates. They function in much the same way as blocks do in Ruby:

irb(main):001:0> h = {:foo=>'bar', :hi=>'there'}
=> {:foo=>"bar", :hi=>"there"}
irb(main):002:0> h.each_key {|k| puts k}
foo
hi
=> {:foo=>"bar", :hi=>"there"}
irb(main):003:0> h.each {|k,v| puts "#{k}: #{v}"}
foo: bar
hi: there
=> {:foo=>"bar", :hi=>"there"}

As you can see, the syntax for blocks in Ruby is quite terse: use curly braces to open and close the block, and use the |x,y| syntax to designate the variables passed to the block.

Blocks in Ruby also act like closures, just as anonymous delegates do in .NET 2.0. This means they have access to values in their enclosing scope, even after that scope has exited. Here’s a simple closure which multiplies together several values:

irb(main):004:0> n = [5, 6, 10]
=> [5, 6, 10]
irb(main):005:0> t = 1
=> 1
irb(main):006:0> n.each { |i| t *= i }
=> [5, 6, 10]
irb(main):007:0> t
=> 300

You can even store references to blocks to be used later:

irb(main):008:0> t = 1
=> 1
irb(main):009:0> f = lambda { |i| t *= i }
=> #<Proc:0x0818a7b0@(irb):9>
irb(main):010:0> n.each &f
=> [5, 6, 10]
irb(main):011:0> t
=> 300

Methods

Method definitions in Ruby are simpler than in .NET, because types are not specified:

irb(main):001:0> def greet(name)
irb(main):002:1> puts "Hello, #{name}!"
irb(main):003:1> end
=> nil
irb(main):004:0> greet "Reader"
Hello, Reader!
=> nil
irb(main):005:0> greet 42
Hello, 42!
=> nil

Ruby performs something called “Duck Typing”: if it walks like a duck and quacks like a duck, it must be a duck. You don’t ask it “are you a duck?”, but rather just assume it’s a duck and call quack on it. Even if you were expecting a duck, anything that can quack is allowed to the party.

When I defined the greet method, I didn’t make any requirements of the objects that can be passed in, because I’m just printing it (and everything in Ruby supports printing, by virtue of the to_s method on Object, which will convert the object into a string). The end result is that you can greet anything.

Here’s another example:

irb(main):006:0> def print_len(item)
irb(main):007:1> puts "Len = #{item.length}"
irb(main):008:1> end
=> nil
irb(main):009:0> print_len "Reader"
Len = 6
=> nil
irb(main):010:0> print_len [1, 4, 9]
Len = 3
=> nil
irb(main):011:0> print_len 42
NoMethodError: undefined method `length' for
42:Fixnum
        from (irb):7:in `print_len'
        from (irb):11

The print_len method now does more than before: it calls the length method on the object passed to it. So the requirement for something to be passed to print_len is that it has a length method that you can call with zero parameters. When you passed a string or an array, it worked, because they have an appropriate length method; passing a number doesn’t work, because the length method isn’t present.

Notice that I didn’t talk about types. In order to write a method like this in .NET, you’d probably need to invent an IHaveLength interface and use that as your parameter type. What about classes that were invented before you created your interface? I guess you’re out of luck, or you end up creating type converters. The whole thing spirals out of control quickly as the strong typing system gets in your way.

On the other hand, at least if you had IHaveLength, you understand what the requirements of the method are. Since types act as a form of documentation, you need an alternative in dynamic languages, which means you will be more reliant on things like written documentation and unit tests to help discern how some class or method is meant to be used.

Ruby supports default argument values:

irb(main):012:0> def repeat(val, times = 5)
irb(main):013:1> val.to_s * times
irb(main):014:1> end
=> nil
irb(main):015:0> repeat "hi"
=> "hihihihihi"
irb(main):016:0> repeat "hi", 3
=> "hihihi"
irb(main):017:0> repeat 10, 3
=> "101010"

Notice that I didn’t place a return before val.to_s * times. Methods in Ruby will always return the result of the last evaluation, unless explicitly told to return a value, so the return keyword is just 7 extra characters you didn’t need to type.

Ruby supports variable arguments:

irb(main):018:0> def add(*values)
irb(main):019:1> result = 0
irb(main):020:1> values.each {|x| result += x}
irb(main):021:1> result
irb(main):022:1> end
=> nil
irb(main):023:0> add 1, 2, 3, 4, 5
=> 15

Ruby packages up the variable arguments into an array, where you take the values that are passed and add them together.

Classes

Classes are templates from which new object instances are created. Let’s put the greet method from above into a class:

irb(main):001:0> class Manners
irb(main):002:1> def greet(name)
irb(main):003:2> puts "Hello, #{name}!"
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> m = Manners.new
=> #<Manners:0x404839c>
irb(main):007:0> m.greet "Reader"
Hello, Reader!
=> nil

Here you’ve created a new class named Manners, and added the greet method to it. Then you create a new instance of Manners, and use it to greet the reader.

When you think of classes being a template for objects in Ruby, you should think of them as a living template. Unlike classes in .NET, which are defined at compilation time, you can extend classes in Ruby at any time, and when you’ve extended them, even existing instances of that class immediately gain the new behavior. Notice what happens when you attempt to say farewell:

irb(main):008:0> m.farewell "Reader"
NoMethodError: undefined method 'farewell' for
#<Manners:0x404839c>
        from (irb):8

When you tried to call farewell, the system told you it didn’t know what it was. Now extend the Manners class and give it the ability to say goodbye:

irb(main):009:0> class Manners
irb(main):010:1> def farewell(name)
irb(main):011:2> puts "Goodbye, #{name}!"
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> m.farewell "Reader"
Goodbye, Reader!
=> nil

After extending the Manners class, your existing instance of it can now bid the reader farewell.

The Manners class has two methods, and both take your name. You should probably re-write it so you can pass the name when you create it. Ruby calls the initialize method with all the arguments you pass to new. You should start over with your Manners class:

irb(main):001:0> class Manners
irb(main):002:1> def initialize(name)
irb(main):003:2> @name = name
irb(main):004:2> end
irb(main):005:1> def greet
irb(main):006:2> puts "Hello, #{@name}!"
irb(main):007:2> end
irb(main):008:1> def farewell
irb(main):009:2> puts "Goodbye, #{@name}!"
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> m = Manners.new "Reader"
=> #<Manners:0x809fa08 @name="Reader">
irb(main):013:0> m.greet
Hello, Reader!
=> nil
irb(main):014:0> m.farewell
Goodbye, Reader!
=> nil

Notice that you’re storing the name in an instance variable named @name. Also take note that the inspection of the instance (the result that’s printed out after line 12) includes the values for all of your instance variables.

The extensibility of classes isn’t limited to just the classes you define. You can also extend the built-in classes in Ruby:

irb(main):001:0> class Array
irb(main):002:1> def print_tr
irb(main):003:2> puts "<tr>"
irb(main):004:2> each { |item|
irb(main):005:3* puts " <td>#{item}</td>"
irb(main):006:3> }
irb(main):007:2> puts "</tr>"
irb(main):008:2> end
irb(main):009:1> end
=> nil
Irb(main):010:0> ["hello","world!"].print_tr
<tr>
  <td>hello</td>
  <td>world!</td>
</tr>
=> nil

Rails adds many extensions to the built-in types that give a sort of fluent interface so you can say things like 5.days.from_now and get back a time zone-aware date that is, well, five days from now.

The methods you’ve defined so far have all been instance methods; that is, they are methods that are available only on instances of a class. What about static methods (sometimes called class methods)? You’ve already been calling a static method, without even thinking about it: new.

You can add new static methods to any existing class:

irb(main):001:0> def String.concat(s1, s2)
irb(main):002:1> s1 + ' ' + s2
irb(main):003:1> end
=> nil
irb(main):004:0> String.concat 'hi', 'bye'
=> "hi bye"

You can also define them in the context of defining or extending the class using the “self” syntax:

irb(main):001:0> class String
irb(main):002:1> def self.concat(s1, s2)
irb(main):003:2> s1 + ' ' + s2
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> String.concat 'hi', 'bye'
=> "hi bye"

Reflection

Reflection is the process of discovering information about objects at run time. You can discover the methods available for a class by calling the methods method. The base class for everything in Ruby is the Object, so here is a look at some of the things available to every object in Ruby:

irb(main):001:0> o = Object.new
=> #<Object:0x3f8feb4>
irb(main):002:0> o.methods
=> ["inspect", "taguri", "clone", "public_methods"
, "taguri=", "display", "instance_variable_defined
?", "equal?", "freeze", "methods", "respond_to?",
    
...many more methods listed...

The result of calling methods is an array of strings with the names of each method available on the object. Remember when I said to think of a class sort of like a Hash? Calling methods is like getting the keys to that hash table.

Knowing the methods wouldn’t be interesting unless you could do something with them, of course. To call the method, you call the send method. The following operations are equivalent:

irb(main):003:0> o.inspect
=> "#<Object:0x3f8feb4>"
irb(main):004:0> o.send "inspect"
=> "#<Object:0x3f8feb4>"

Ruby gives you an opportunity to handle unknown methods by defining the method_missing method on your class:

irb(main):139:0> class Object
irb(main):140:1> def method_missing(*args)
irb(main):142:2> puts args
irb(main):143:2> end
irb(main):144:1> end
=> nil
irb(main):145:0> o.foobar 1, 2, 3
foobar
1
2
3
=> nil

As you can see, the arguments passed to method_missing include the requested method as well as all the arguments passed to that method. A better definition would probably be:

def method_missing(method, *args)

Meta-Programming

Although Ruby does not have properties, you can use the fact that method invocation does not (usually) require parenthesis to simulate properties. You also need to leverage the fact that Ruby treats methods that end with = specially, making them act like setters.

You might define a person class as such:

irb(main):001:0> class Person
irb(main):002:1> def age
irb(main):003:2> @age
irb(main):004:2> end
irb(main):005:1> def age=(value)
irb(main):006:2> @age = value
irb(main):007:2> end
irb(main):008:1> end
=> nil

Now you can use instances of Person, and treat age like a property of the person:

irb(main):009:0> p = Person.new
=> #<Person:0x89c5678>
irb(main):010:0> p.age
=> nil
irb(main):011:0> p.age = 42
=> 42
irb(main):012:0> p.age
=> 42

If you wanted age to default to something other than nil, you could set it in the initialize method.

Looking at this code, it feels very boilerplate. If this were a language like C#, you’d probably be tempted to use things like snippets in Visual Studio or even static code generation to automatically generate the reader and writer of a property.

With Ruby, though, you can use meta-programming to create these things with just a small amount of effort. Ideally, you’d like to be able to write something like:

class Person
  prop :age
end

You’ll define a class (static) method on Object so that it’s available to use when you’re defining your class. You’ll also use a method you haven’t seen before now: the class_eval method:

irb(main):001:0> class Object
irb(main):002:1> def self.prop *names
irb(main):003:2> names.each { |name|
irb(main):004:3* self.class_eval "
irb(main):005:3" def #{name}
irb(main):006:3" @#{name}
irb(main):007:3" end"
irb(main):008:3> self.class_eval "
irb(main):009:3" def #{name}=(value)
irb(main):010:3" @#{name} = value
irb(main):011:3" end"
irb(main):012:3> }
irb(main):013:2> nil
irb(main):014:2> end
irb(main):015:1> end
=> nil

The class_eval method as used above is what ends up creating the methods. It evaluates the string as though you’d done that in the context of the class itself. So you can write your methods just as if you’d been writing them inside the class all along.

For each name you were passed to the prop method, you add two methods to the new class: a getter and a setter. Because the string gets replacement done on it, the end result string replaces #{name} with the name that you passed to the prop.

Now you can use prop in your class definition:

irb(main):016:0> class Person
irb(main):017:1> prop :age, :name
irb(main):018:1>
irb(main):019:1* def initialize(age, name)
irb(main):020:2> @age = age
irb(main):021:2> @name = name
irb(main):022:2> end
irb(main):023:1> end
=> nil
irb(main):024:0> p = Person.new(36, "Brad")
=> #<Person:0x89c0768 @age=36, @name="Brad">
irb(main):025:0> p.age
=> 36
irb(main):026:0> p.name
=> "Brad"

When you have these kinds of facilities at your disposal, you can see that you can quickly create classes at a much higher level, and use these kinds of meta-programming tricks to do much of the work for you, without needing to rely on editor snippets or compiler-time code generation.

Summary

I’ve really just scratched the surface of the facilities available in Ruby. Learning Ruby today will help you prepare for when Ruby is available on .NET and in Silverlight. Having such a powerful dynamic language will be a welcome addition to your programmer’s tool belt, but more importantly, it will help you start to think about problems and solutions in a new way.

To continue your Ruby education, I strongly recommend Programming Ruby: The Pragmatic Programmer’s Guide by David Thomas and Andrew Hunt (Addison-Wesley Professional), sometimes called “The Pickaxe” for its cover picture.