Tuesday, March 10, 2009

GTFO my Ruby, C users

Alternatively: Lies revisited.

It's often stated that Ruby has no primitives, everything is an object. That's not true, rather almost everything is actually a pointer to an object. There is also one primitive: int. They've just been made to behave as objects through other means. Ints are primitive as an interpreter optimization, since you're going to be storing int values in pointers, there isn't much to be gained in constantly creating int objects and then pointing to it, at least in Ruby's case.

What's really interesting is the objects:

a = 'hello world'
b = a
a = 'goodbye world'

puts a #outputs goodbye world
puts b #outputs hello world


Wait, what happened there? Well, since Ruby is meant to be intuitive (this isn't C after all), we don't want to be dealing with all this pointer nonsense. Everything is made to behave as though they were passing by value, so treating everything as an object works. Mostly. What actually happens behind the scenes is that b still points to the old value, but when a is changed, a new value is created and a is redirected to that. If we change b as well, then our garbage collector sees that 'hello world' is unref'd and reclaims the memory (this isn't C goddammit).

Ruby gives us some options for changing values directly:

a = 'hello world'
b = a
a.replace('goodbye world')

puts a #outputs goodbye world
puts b #outputs goodbye world


In addition to that, there are a number of bang (!) functions, which behave like their counterparts except that they modify values directly. The ! signifies that they're dangerous.

So what happens? Well, knowing this information, a user decides to suggest in a thread that Ruby ought to have pointers to pointers so he can do things like he could in C.

Because .replace is too messy.

Nevermind that Java gets along just fine without any.

Fucking C.

Yeah, that was a long setup to a bad punchline. I know. I also know that the interpreter was coded in C.

No comments: