.NET the Ruby Way

MSDN's Channel 9 recently ran an interesting interview with Dr. Wayne Kelly, the creator of Ruby.Net. Having some experience with .NET, and being a local Ruby evangelist, this seemed like a great opportunity to test the waters. Each language has its strong points, and having a strong interop interface would certainly be a big plus. Let's see how far we can get.

Running Ruby with .NET

Latest beta (0.6) of Gardens Point Ruby.NET compiler claims to pass all 871 tests in the sample suite for Ruby 1.8.2, which doesn't give us the whole playing field, but it should suffice. To test this claim, I extracted a couple of methods from my own collection of Ruby extensions. Specifically, since Ruby is great for quick and dirty data manipulation, I added a couple of methods for calculating Shannon's entropy of a string. Here is a quick Ruby mock up:

class String
  # Calculate Shannon's entropy (number of bits required to encode a string)
  def entropy
    arr = self.split(//)
    probHash = arr.probability
    h = -1.to_f * probHash.keys.inject(0.to_f) do |sum, i|
      sum + (probHash[i] * (Math.log(probHash[i])/Math.log(2.to_f)))
    end
    h
  end
end

class Array
  # Return a hash, mapping each item in the array to its probability
  def probability
    probs, size = Hash.new(0.0), 0.0
    each do |e|
      probs[e] += 1.0
      size += 1.0
    end
    probs.keys.each { |e| probs[e] /= size }
    probs
  end
end

# Some mock Ruby code to play with in .NET
module RubyNet
  class RubyClass
    attr_accessor :var1, :var2

    def initialize(var1, var2)
      @var1, @var2 = var1,var2
    end

  end
end

# Let's test it in ruby
obj = RubyNet::RubyClass.new(1,2)

p "aa".entropy      # 0 bits
p "ab".entropy      # 1 bit
p "abcd".entropy   # 2 bits

After verifying that the Ruby code is correct, I downloaded the binaries for the Ruby.NET compiler, and let it do its magic:

$ F:\Ruby.NET.beta0.6.bin>RubyCompiler.exe --exe rubynet.rb
$ F:\Ruby.NET.beta0.6.bin>ruby rubynet.rb
0.0
1.0
2.0
$ F:\Ruby.NET.beta0.6.bin>rubynet.exe
0.0
1.0
2.0

Impressive! Now I don't have to force my friends to install Ruby to run my snippets, I can simply convert the file, attach a few dll's into the package and let them run my code as they wish. Of course, this assumes they have .NET installed, but that's beside the point!

Using Ruby code libraries in .NET!

How would you like to package your Ruby methods/libraries into a dll and make use of them in .NET? Sounds too good to be true, and alas, it is at the moment. Ruby.NET is still in very early stages, and it will be interesting to see how it develops, but for now, access to Ruby methods is still missing. Having said that, after some fiddling with .NET, I managed to get as far as playing with instance variables inside the mock RubyClass:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Ruby;

namespace ConsoleApplication {
    class Program {
        static void Main(string[] args) {

            // Instantiate a RubyClass object!
            Ruby.Object r = new rubynet.RubyNet.RubyClass();

            // Fiddle with the instance variables
            r.instance_variable_set("var1", 5);
            object t = r.instance_variable_get("var1");
            System.Console.WriteLine(t.ToString());

        }
    }
}

Recompiling the ruby file with the dll flag (--dll), and adding a reference to it in my visual studio project allowed me to dig into the library and extract a few accessible method calls. And sure enough, after building and running the project, we get:

$ F:\ConsoleApplication2\bin\Debug>ConsoleApplication2.exe
5
rubynet.zip - Ruby + Compiled .NET binary and DLL

I have a feeling that this is just a taste of things to come, and the wiki seems to confirm my beliefs. Either way, Ruby.NET is definitely a project worth keeping an eye on, especially if you're exposed to .NET in any shape or form. Personally, I'm definitely looking forward to playing with future releases!


Ilya Grigorik

Ilya Grigorik is a web performance engineer and developer advocate at Google, where his focus is on making the web fast and driving adoption of performance best practices at Google and beyond.