Rubinius runs RSpec 1.1.2

January 17th, 2008 | 3 comments

This day has been a long time coming. About a year ago, I started trying to get Rubinius to run RSpec. Hats off to all the wonderful Rubinius contributors and special mention to the cool guys who hung out with me at pdx.rbc meetups in early 2007. (Unfortunately, the page in that link will disappear soon. Maybe I’ll make a pdf out of it and keep it here. You know, nostalgia.)

Everyone’s efforts have paid off and here is the proof:

$ shotgun/rubinius -I ../rspec-1.1.2/lib/ ../rspec-1.1.2/bin/spec spec/ruby/1.8/core/true/
.....

Finished in 0.988572 seconds

5 examples, 0 failures

The TrueClass specs were some of the very first ones I wrote, so I thought it fitting those be the first ones I ran successfully with RSpec.

Congratulations everyone!

Contra--what?

January 17th, 2008 | 0 comments

I’m going to be pedantic for a minute. If you are Betrand Russell, feel free to spend your time more productively. Everyone else, don’t be afraid of a few symbols.

If you read my last post, you might be inclined, as is every human mind, to reduce all those words to something simple you can put in your back pocket (maybe take it out later and show it to a friend). Perhaps something like this:

  Immutable == Security == Good

If you do that, you might get lots of nods and a fair bit of affirmation from folks. Makes perfect sense, right. You can make all sorts of analogies that prove this to you. Consider my front door, if it’s not easily opened, I feel more secure. Perfect. Must be true.

It’s not. Things are not so easily distilled into such nifty little boxes.

Now, once they have this shiny, handy, palm-sized summary in their back pocket, folks tend to go the extra mile. They decide to make one of the most fundamental logic errors. Essentially, trying to think all the way around this hairy problem, they decide:

  If Immutable == Security
  Then Not Immutable == Not Security

Doh. That’s where this contra thing comes in. Read the gory details on Wikipedia, but here’s the summary:

In logic, something like A -> B is read “A implies B” or “if A then B”. It is very tempting to then think, “if not A then not B”. Unfortunately, that is not generally true. Given “A implies B”, the statement “if not A then not B” is called the inverse. Again, these are not generally logically equivalent. The statement “if not B then not A” is called the contrapositive, and it is generally true that a statement and it’s contrapositive are logically equivalent.

Applying this to the above, we can see that IF (a very big if) it is true that “if Immutable then Secure” is true, then the statement “if not Secure then not Immutable” is equivalently true. However, it has not been demonstrated that immutability is equivalent to security. And indeed there are numerous ways to achieve “security” (a word that begs precise definition) in a variety of different systems.

So, before you start touting something like Java because it is statically typed, immutable and “secure”, consider whether you are making the mistake of confusing the inverse for the contrapositive. If you’re feeling extra nimble and up for some mental gymnastics, consider this rather hyperbolic assertion:

Ruby is a very, very sharp knife. Java is a little more like a butter knife. We safely leave butter knives on the table when the kids are around. But, we probably grumble more than a little when trying to cut our steak with a butter knife.

If we want to make Ruby “safer”, it’s possible to do so in the same manner as dealing with sharp knives: we make something like a sheath. We don’t just take a hammer to the blade and dull it.

Evil can be dangerous

January 16th, 2008 | 3 comments

The first post I read by Evan about Rubinius had a quote about evil built in. Of course, that caught my eye. What was Evan’s point? Legend has it (I wasn’t there) that during Q&A someone asked about fundamental aspects of the Rubinius system being available for modification from normal user code. The issue was raised that perhaps something should restrict that unlimited power. Evan’s response was that Rubinius sorta has evil built in. Usually, that’s a good thing.

In fact, it’s a very sharp double-edged blade. We all cherish the dynamic nature of Ruby when it allows us to do useful things. For example, the following works great in MRI:


class Fixnum
  alias / quo
end

That little snippet and you’ve redefined fixed-point math to return a floating point number. That gem is one of the core pieces of the Mathn library in the Ruby standard library collection. Together with the Rational library, you can do some cool stuff:


$ irb
>> require 'rational'
=> false
>> require 'mathn'
=> true
>> 1 / 2
=> 1/2
>> 1 / 2 + 3 / 8
=> 7/8

Combine that with Matrix and Rational and you have at your disposal some pretty powerful tools for doing more realistic mathematics. Take a look at what some folks do with it.

Fortunately, and unfortunately, Rubinius is very different than every other implementation of Ruby that I’m aware of. Rubinius follows the Smalltalk model and uses the Ruby language itself to build the implementation. That means that Array, for instance, calculates values for its internal operations using none other than the same Fixnum values that you use in your Ruby code. So, what happens when we redefine Fixnum#/ to return a Float instead?

Yes, you guessed right. Things work differently. In fact, not at all.

Since we’re not about to rescind the promise of a better Ruby, we have to figure out some way to deal with this. There are several approaches possible. One would be to code all of the core library with a different set of numeric classes, say BasicFixnum and BasicBignum, that are superclasses of Fixnum and Bignum. That would be really cumbersome. Another approach would be to use different methods in the core library. Again, cumbersome. So, this sounds like there are some basic goals we have in mind. In fact, there are. We want to keep the core library code as simple as possible and provide the full power of Ruby at every level, to the greatest extent possible.

This isn’t necessarily the ultimate approach we’ll use, but I checked in some code today that leverages a very slick feature that Evan built into the compiler. I created the following compiler plugin:


class SafeMathOperators < Plugin
  plugin :safemath

  MathOps = {
    :/ => :divide
  }

  def handle(g, call)
    name = MathOps[call.method]
    if name and call.argcount == 1
      call.emit_args(g)
      call.receiver_bytecode(g)
      g.send name, 1, false
      return true
    end
    return false
  end
end

Essentially, what this does is map any calls to the #/ method to the #divide method. I’ve changed the core library classes Fixnum, Bignum, Float, and Numeric to handle this. So, the code in core looks the same, but is protected from the redefinition that the Mathn library performs. The compiler plugin is activated with the -frbx-safe-math switch only when compiling the Rubinius core libraries.

UPDATE: Note that you do not have to do anything differently. The compiler flag is passed in automatically when you type rake to build the Rubinius libraries. If you are writing user code, you also do not need to do anything differently. You just write your code as you normally would. If you require the Mathn library, 1 / 2 => 0.5. If you also require the Rational library 1 / 2 => 1/2. Invisible, maybe even a little evil.

Again, this is not necessarily the way we’ll always do it. The lessons are:

  1. Ruby is a great, powerful language
  2. Rubinius makes Ruby even more powerful
  3. We can work around snags pretty dang easily, even if temporarily

Of course, we’re always learning. Any papers, systems, code, etc that you can point me to?

Irb in the house

January 5th, 2008 | 0 comments

I’m going to give this live blogging thing a go. As of 14:52 PST, Evan announced that Rubinius runs irb. It hasn’t landed in the repository yet, but this is great news. Just a little while ago, we started with an irb wannabe. I guess a lot can happen in a year.

Congrats to Evan and all the fantastic Rubinius supporters and contributors.

UPDATE: So, I’m not a very good reporter. There’s some other very big news related to getting irb working. Evan checked in a working eval yesterday. Enjoy!