A .NET Guy Looking at Some Ruby

I’m thinking it would be nice to relearn the basics of Ruby (which seems to gain more and more popularity) and compare it to some of the dynamic features .NET 3.5 has been blessed with. I’m also interested in where the Microsoft version of the language, IronRuby, is now and how I can use the .NET libraries from it. I installed and looked at Rails some (long) time ago now, but I never got the chance to use it and my minimal Ruby skills have now faded to nil again. So this is me taking it up again, hoping I can use it for something real, perhaps for unit testing or just test driving some .NET code with the help of IronRuby.

What you’re reading is just me scratching down notes as I go along, it’s not an article or so, this is just for me to have something to get back to later on, so bear with me. I will probably write down things that are not right or make wrong assumptions, but I’m happy to get comments if you see something awfully wrong.

Edit: I had to change the section on line continuation, because I was wrong about what I first wrote.

Getting Started

So how do I get started? First I need a Ruby implementation for the platform I’m running on, in my case Windows Vista. On RubyForge there is a Windows installer for Ruby which contains everything you need to get going. It’s available on http://rubyforge.org/projects/rubyinstaller/ and I’m going for it. Later on I’m also going to download and build IronRuby and .NET applications using the Ruby language, but you will still need Ruby installed to build IronRuby. The IronRuby website www.ironruby.net has some notes on all this, but I’ll blog on that later I think.

The installer will give you the Ruby language, runtime and an editor called SciTE. It also includes a samples directory which may come in handy. With Ruby you got several options to create and test small console apps. After the installation completes, just open up a command prompt and type “irb” and you’ll get an interactive Ruby command prompt, which is very handy for both testing and learning. Another option is to go to the Start menu and use “fxri”, which is a graphical interface to the Ruby documentation and also includes an interactive Ruby console. I’ve used both today. Fxri is great when you’re looking at someone else’s Ruby code and you see a command or class you don’t recognize.

The Ruby installer also comes with an electronic version of the book “Programming Ruby - The Pragmatic Programmer's Guide” by Dave Thomas – which I can tell is also a great source for knowledge. I’ve not read it yet, but I’ve used it to look up certain things.

Tutorials

Next I need some getting started articles or such, and there are tons of it on the Internet. You could use the book above, but I’m looking for something which will get me into the dirt quickly.

I found a “Learning Ruby” website by Daniel Carrera which looks promising, and I’m using it to learn the very basics. You’ll find it at http://www.math.umd.edu/~dcarrera/ruby/0.3/index.html  and it’s using the “irb” console in its first steps, which works perfect with IronRuby. Just open up a command prompt and type:

irb --simple-prompt

You'll be greeted with a prompt like this…

>>

…and off you go. Just type your code and press enter. There are other great intros to Ruby on the Internet, and this one by Steve Litt looks good, http://www.troubleshooters.com/codecorn/ruby/basictutorial.htm

Variables and Strings

Most tutorials start with numbers, strings and variables. There’s not much to say about Ruby variables – you don’t have to declare them, just initialize the variable with a value and start using it:

i = 1

Exactly what I’m expecting from a dynamic language, and strings are very easy to work with:

name = "Johan"
name = name + " Danforth"
puts name

The string class in Ruby has a number of powerful methods you can use to work with, same as with the string class in .NET, but the Ruby string class has more than 100 methods on it (from counting the methods in fxri). The .NET string class has around 70 methods, but 45 of these are extension methods that are new to .NET 3.5, and I think many of them were inspired by dynamic languages just like Ruby. I have to say though that some of the methods in Ruby do the same things sort of and some methods are quite funny. Like squeeze, chomp, chop and such :) Methods for parsing, encoding, converting and such are also included in the Ruby string class, functionality that may be baked into other libraries in the .NET framework.

Running a Ruby Program File

Running a Ruby program from a file is dead easy. From the console type “ruby myprogram.rb” and press enter. The installer also associates the .rb file extension with the Ruby executable, so it’s possible to just type “myprogram.rb” or click the file from Windows Explorer.

A good editor for your .rb programs seems to be SciTE which also comes with the Ruby installer. Just open up the editor, type the program and press F5 to run it (make sure you have saved it with the .rb file type). The results will be shown in the right pane of the SciTE editor. Nifty.

Type Conversion

What strikes me as odd is that Ruby is a dynamic language, but automatic type conversion is sometimes not as good as I would think, and something as simple as this will give you an error:

sum = 1 + 2
puts "The sum is " + sum

test.rb:2:in `+': can't convert Fixnum into String (TypeError)

So, in a print statement like the above, Ruby won’t convert the number variable into a string like c# or VB does:

Dim sum = 1 + 2
Console.WriteLine("The sum is " & sum)

You’ll have to convert the sum variable to a string like this:

puts "The sum is " + sum.to_s

Aesthetic Code

Ruby seems to be much about the aesthetics of the code you write. Most Ruby tutorials seem to bring up naming of variables, classes and methods in an early state. What is funny is that the casing of a variable matters to the interpreter, because if you uppercase a variable, it’s treated as a constant. You can change the value of a constant, but the runtime will give you a warning:

PI = 3.14
puts PI
PI = 3.14159265
puts PI

test.rb:3: warning: already initialized constant PI
3.14
3.14159265

But what about code statements that are too long? In c# you can make a line break after almost any statement, and it's the same thing in Ruby. I was wrong about this at first, because in Ruby (as in VB) you can put a backslash (underscore in VB) at the end of the line to do break up a line of code: 

 puts "this is a " + "very " +
  "long statement"

Be careful not to put a space after the backslash, or you’ll get a strange looking error:

test2.rb:1: syntax error, unexpected $undefined
puts "this is a " + "very " + \
                               ^

I’m not fond of the line continuation underscore thing in VB, and I’m thinking the same of the backslash in Ruby, so you won't see me use it.

Loops

Ruby seems to be good at this, and the most common syntax for-loops is easy to read and pretty nice:

i = 1
4.times do 
  puts "pass " + i.to_s 
  i += 1
end

Well, this is just like any other for-loop out there, but the syntax is nicer. There are other ways to type the same thing in Ruby but I’ll get back to that later. I know people have tried to come up with a similar syntax using .NET 3.5 method extension and lambda expressions, but I think it’s hard to make it as compact as in Ruby. My 10 minute feeble attempt at making a c# version of the Ruby times-method would probably be an extension method like this:

        public static void times(this int number, Action codeblock) 
       
            while (number-- > 0) 
                codeblock(); 
        }

And I could call it with a one-liner lambda expression like this:

            var i = 1; 
            4.times(() => Console.WriteLine("hi! " + i++));

Or with a delegate (with some richer code inside) like this:

            var i = 1; 
            4.times(delegate(){ 
                Console.WriteLine("pass " + i); 
                i += 1; 
            });

Not as nice as the Ruby variant, but close :) The System.Action Delegate class in .NET 3.5 is pretty awesome btw, and you got a generic version of it as well if you need to pass arguments on to the delegate.

Of course Ruby has the traditional VB-like “for” statement as well, with a couple of variations. A 1-5 for-loop looks like this:

for x in 1..5 
  puts x
end

But a 1-4 for-loop looks like this, see the difference?

for x in 1...5 
  puts x
end

2 periods mean as long as the variable is less than or equal to the “to” value (inclusive), 3 periods mean as long as the variable is less than the “to” value (exclusive). I’m sure this is a common coding mistake, as it’s easy to miss. And as you can see, no braces/brackets like in c#, so I guess VB programmers feel a bit more comfortable with this syntax, but the for-loop statement in Ruby is, I believe, syntax sugar for this statement, which involves braces/brackets but equally valid:

(1...5).each {|i| puts i }

Conditional Statements

Conditional statements, in Ruby are a bit of a mix between VB and c#. Like in c#, “=” assigns values and “==” compares. I like that. For example:

a = 1
if a == 1 then 
  puts "true" 
  else 
    puts "false" 
  end

Arrays and Lists

Arrays in Ruby have much in common with the same in c# and VB.NET, especially with the new features in .NET 3.5. Ruby is zero based, so you address a specific item in the array with [] , and it’s possible to initialize arrays in a similar way in all languages. In Ruby:

  numbers = [ "zero", "one", "two" ]
  addresses = [ [ 10, "Kings Rd" ], [ 25, "Queens Rd" ] ]

Initializing a simple string array in c# 3.5 is quite similar:

 var numbers = new[] { "zero", "one", "two" };

The “addresses” array can be solved in many different ways in .NET, but I think the c# equivalent would be: 

var addresses = new[]

           new object[] {10, "Kings Rd"}, 
           new object[] {25, "Queens Rd"}
};

As you can see, c# requires a bit more typing. Personally I prefer to create an array of anonymous types in c#, as it is much easier to code against:

var addresses = new[] { 
           new  { Number=10, Street="Kings Rd" }, 
           new  { Number=25, Street="Queens Rd" }
};

The VB.NET equivalent of a simple string array and array of anonymous types is something like this I think (I’m not a VB-guy):

        Dim numbers() = {"zero", "one", "two"
        Dim addresses() = {New With {.Number = 10, .Street = "Kings Rd"}, _ 
                           New With {.Number = 25, .Street = "Queens Rd"}}

Oh, the number of things you can do with arrays in Ruby, and in a very intuitive way too. Reverse, sort, add, remove and other methods we recognize from -.NET List and List<> types, but like the Ruby string class there’s a number of unusual but powerful methods on Ruby arrays like flatten (sample taken from the docs):

  s = [ 1, 2, 3 ]            #=> [1, 2, 3] 
  t = [ 4, 5, 6, [7, 8] ]  #=> [4, 5, 6, [7, 8]] 
  a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] 
  a.flatten                   #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10

If I coded Ruby for 10 years, I’m not sure I would ever use that method :) It flattens an array of variable length arrays into a one-dimensional array recursively. Cool to have this method built into the Ruby language from scratch.

But other than a few methods like this, it feels like you can do about the same things with the .NET lists and arrays. You may have to turn your array into a list or vice versa, so again we’re talking a little bit of more code than Ruby, but not too much.

Iterators

Related to arrays are of course iterators. A common way to iterate through a Ruby array is to use do – end like some of the samples above. But there is a cool way to use a similar syntax, each – do – end  and pass the current item of the array into a block of code. This seems to be a common style of coding in Ruby:

friends = ["Melissa", "Jeff", "Ashley", "Rob"]
friends.each do |friend| 
     puts "I have a friend called " + friend 
   end 
  

   5.times do |i| 
     puts "pass " + i.to_s 
   end

It’s quite possible to use a similar style of coding in c#, by using a foreach loops, lambda expressions or delegates:

var friends = new[] {"Melissa", "Jeff", "Ashley", "Rob"};

foreach(var friend in friends) 
           Console.WriteLine("I have a friend called " + friend);

5.times(ii => Console.WriteLine("pass " + ii));

 

public static void times(this int number, Action<int> block)

    int i = 0; 
    while (i < number) 
   
        block(i); 
        i++; 
    }
}

As you can see, I’m using a method extension to create my own times() method, using a lambda expression to pass a block of code to the times() method with the help of the generic Action delegate. It’s a variation of the times() method I used earlier.

Sometimes when the loop just contains one line of code some Ruby coders seem to replace the do – end with curly braces like this:

6.times { |i| puts "pass " + i.to_s }

As I mentioned earlier when I wrote about loops, this is just another way to type it. If the compiler turns the do-end into braces or vice versa I don’t know – it just works.

The “each” keyword in Ruby seems to be pretty powerful and lets you iterate through different sorts of lists in many ways. It is also used to handle hash-tables. A hash-table in Ruby is declared and initialized like this:

fruits = { 
 "123" => "Apple", 
 "456"  => "Banana", 
 "789"    => "Orange"
}

As you can see, we’re using squiggly/curly braces/brackets instead of squares. Not sure why it is like this and I would have preferred to use squares here to as for arrays, but this apparently is the way… To access a particular value, just address it with the key of course:

puts fruits["123"]

And iterating through the table with the each – do – end syntax is starting to feel natural now:

fruits.each do |key, value| 
 puts key + " => " + value
end

Of course you don’t need to use the names “key” and “value”.

It’s quite similar to the way most other languages handle hash-tables. Hash-table declaration and initialization in c# is quite similar thanks to the new language features in c# 3.5:

var h = new Hashtable
           {"123", "Apple"}, 
           {"456","Banana"}, 
           {"789","Orange"}};

Sorting Your Own Way

In c# lists and arrays there are ways to do your own custom sorting, but in Ruby it’s done in a different way. You write your own sorting in-line in a sort – do – end loop like this for example:

friends = [ 
    [ "Johan", "Danforth" ], 
    [ "Eric", "Quist"],
    [ "Björn", "Poppe" ]
]

friends = friends.sort do |a,b| 
  a[1] <=> b[1]   # compare last names
end

Nice thing here is that is seems to be quite simple to do custom sorting of arrays with complex objects in them. The <=> operator is something which is built into Ruby because sorting and comparing is so often done. Basically a <=> b,

- returns -1 if a is less than b

- returns 0 if a is equal to b

- returns 1 if a is greater than b

The operator is able to work with strings and numbers.

That’s Enough for Now

I think this is enough for now. I’ll post a follow up about methods, classes, inheritance and such later on.

2 Comments

  • Your statement about converting to string is not altogether correct:

    puts "The sum is " + sum.to_s

    could be: puts "The sum is #{sum}"

    which is very similar to: Console.WriteLine("The sum is {0}", sum);

    IMHO the second ruby syntax is much cleaner than any form of string concatenation in either langage. This syntax is also available in Perl and others.

  • Jho, you're absolutely right. Maybe I'll update the blog post.

Comments have been disabled for this content.