Ruby is a remarkable language, and even companies like Microsoft and Sun, end up taking notice of, and embracing, it rather than opting to fight against its widespread appeal. More than ever Ruby is seen as an unwritten (sic) specification that is not limited to its official implementation. The main current interpreter is suboptimal as we all know. This scenario has one big advantage, though it may appear as a disadvantage at first: projects keep popping up in a quest to generate an efficient and widely adopted interpreter/virtual machine. Generally speaking, this diversification is a risky business because it can’t help but divide the effort put forth towards it by those within the community. Years of Open Source history have taught us though that options are usually a good thing and the majority of development efforts will still go towards the most promising projects. We allow mutations of an original idea into multiple projects, and in turn let a sort of natural selection decide their destiny and long term adoption.
In the specific case of Ruby, besides the current interpreter, JRuby is the most prominent implementation. Other notable mentions are Yarv – the work in progress at the core of what will be Ruby 2.0 -, Rubinius, Ruby .NET (formerly Gardens Point Ruby .NET) and now IronRuby. JRuby and IronRuby are directly developed and promoted by the producers of the two mainstream platforms, respectively Sun and Microsoft. Their interest goes beyond the simple issue of putting out a Ruby implementation which performs well, that is already being answered by Yarv. What they bring to the plate is the possibility of integrating Ruby with the existing code base respectively for Java and .NET. This is a key point, because let’s face it, despite its success, Ruby is not going to replace Java or C# in the mainstream market over the next few years (if ever). Interoperability is exciting as it is synonymous with removing the barrier of entry to Ruby for the Enterprise world and non-Open Source based shops. Simply stated, we’re not asking them to toss their Java or .NET investments out the window, but rather we’re enabling them to take advantage of the rapid development which is possible through Ruby – while still using very refined tools, the existing code base, and a platform which they are accustom to.
By now you should get that I’m highly interested in the development of these implementations, particularly for the .NET and Mono platforms where beautiful GUI development works well. And while I’m afraid that Microsoft will continue to strongly influence the “natural selection” process that we covered above, limiting the Ruby.NET project which is about to be open-sourced by Queensland University, I can’t help but feel excited about IronRuby. So why the mildly negative title of this article, you may ask. On July 23th, John Lam announced the release of a first pre-alpha version which is available for download. This arrived sooner than expected, and Scott Guthrie – General Manager within the Microsoft Developer Division – even showed us some shiny windows made with IronRuby and WPF. Not only this, John also announced that they will be soon taking contributions for the IronRuby libraries and that they will host the project at RubyForge (wow, they must have Lawyers 2.0 as well :-P) and that they have some interesting micro benchmarks. This is all great, so again what’s the issue? Well, I was very interested in trying out IronRuby, but I immediately discovered that it is very crippled from a mathematical standpoint, even for a pre-alpha version. I have a lot of respect for John Lam and the people working on this, and I do understand that it’s a first drop of code and therefore basically in its infancy and that in turn we can’t, in all fairness, have unreasonable expectations at this stage. However after running some simple tests, it is clear that a lot of work is required in order for this project to live up to the buzz that is being generated online about it, when you take into account that even some simple arithmetic functionalities are either flawed or missing altogether.
Some basic calculations
If you build IronRuby and run rbx.exe, you will find yourself in a .NET enabled version of irb. By the way, it may be a good idea to change that name as it is the one already adopted by Rubinius and possibly by spyware on Windows. Let’s see what happens when we do some basic calculations:
>>> 1/3.0
=> 0
As you can see, this incorrectly converts 3.0 to the integer value and then performs an integer division. If you run this in the official Ruby interpreter, and presumably in any other implementation, you will get 0.333333333333333. Trying to be forgiving on this one by using a floating point number for the numerator as well, makes things worse:
>>> 1.0/3.0
System.MissingMethodException: undefined local variable or method `/' for 1:Float
at Ruby.Builtins.Kernel.MethodMissing(CodeContext context, Object self, Proc proc, SymbolId name, [...]
We can’t divide two floating point numbers in IronRuby? OK, let’s stick with Fixnum (small integer numbers) and perform another basic mathematical operation: the exponentiation.
>>> 2**3
System.MissingMethodException: undefined local variable or method `**' for 2:Fixnum
at Ruby.Builtins.Kernel.MethodMissing(CodeContext context, Object self, Proc proc, SymbolId name, [...]
This didn’t work either (of course, we were expecting 8 as a result). So while calculating several multiplications, I noticed another problem:
>>> 1_000_000 * 1_000_000
=> -727379968
The safety of performing calculations with big numbers (without having to deal directly with overflows) is an important aspect of Ruby. While the Bignum class appears to be defined:
>>> Bignum.class
=> Class
It is clear that it is not implemented and it’s only there as a placeholder at the moment:
>>> 5.class
=> Fixnum
>>> 10_000_000_000.class
System.NotImplementedException: The method or operation is not implemented.
at Ruby.Compiler.Tokenizer.StringToNumber(String buffer, Int32 bas) in C:\Documents and Settings [...]
Conclusion
Please don’t take this as an attempt to bash IronRuby, as it most certainly is not intended as such. I have great expectations for this project and look forward to writing lots of Ruby code running on both .NET and Mono through IronRuby. Also, the developers have done a great job at coming up with a preliminary implementation in a very short amount of time. However, when you read about IronRuby and talk about it as the next great thing in the Ruby world, keep in mind that they were not kidding when they called it a “pre-alpha1”. I look forward to documenting the progress of this project on this site, and I will definitely continue to keep an optimistic eye on IronRuby.
Get more stuff like this
Subscribe to my mailing list to receive similar updates about programming.
Thank you for subscribing. Please check your email to confirm your subscription.
Something went wrong.
Ruby really needs a formal specification 🙂
We were afraid IronPython changed Python’s implementation instead of sticking as much closer to CPython as they can get but I think with IronRuby their job is tougher 🙂
>>> 1.0/3.0
System.MissingMethodException: undefined local variable or method `/’ for 1:Float
at Ruby.Builtins.Kernel.MethodMissing(CodeContext context, Object self, Proc proc, SymbolId name, […]
>>> 2**3
System.MissingMethodException: undefined local variable or method `**’ for 2:Fixnum
at Ruby.Builtins.Kernel.MethodMissing(CodeContext context, Object self, Proc proc, SymbolId name, […]
Why don’t rewrite the post after IronRuby gets these methods implemented?
Hi Antonio,
You’re correct – we haven’t implemented many numerical operations. You can look at the source code in FixnumOps and FloatOps to see exactly the extent of our implementation.
If you want to have some fun, try implementing the code that would fix the behavior in the 1/3.0 case that you described. It should only take about a minute or two.
We also have a very efficient BitNumber library (look under the Microsoft.Scripting directory) that we developed for IronPython (and that Ruby.Net uses in their implementation).
But we haven’t had the chance to hook up those methods yet. In prioritizing the features for this release, it was roughly:
1) Get block/method dispatch working using efficient DLR mechanisms.
2) Get control flow semantics working
3) Get some basic types working: Array, String
4) Get .NET interop working
Hope that helps,
-John
Probably these are just bugs. If it doesn’t behave the same as regular ruby, it is a bug. Remember ironruby is only a 2 day old preview release.
Looking at Lam’s announcement, I also see this:
require ‘System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’
“Notice how you need to use the fully-qualified assembly name in require.”
That is awful. Hopefully they’ll fix that too.
See http://fepy.blogspot.com/2007/07/teaching-ironruby-math-tricks.html for my answer to this enquiry.
Hi Antonio,
I’ve written quite a detailed tutorial on how to easily hack IronRuby and extend it using Visual C#. It’s here:
http://www.yashlabs.com/wp/?p=145
Best
I’m digging through the source code of IronRuby and I find it quite elegant and understandable, I’m enjoying it and it seems pretty easy to spot and than fix bugs or implement missing methods or functionalities. I hope to see a growing lot of contributors around IronRuby, but the start was good and I’m very optimistic 🙂