Ruby on... Gemstone? 2

Posted by Christopher Smith Wed, 30 Apr 2008 23:02:00 GMT

Really, when you think about it, how can a company called Gemstone NOT get involved with a language called Ruby. So, Gemstone, of Gemstone and GLASS fame, have apparently decided to get the traditionally lackadaisical Ruby runtime running on their VM. From the first time I dabbled with Ruby it seemed like “file-based Smalltalk with some ugly Perl-isms and a crappy VM” (and yes, in fairness, the ugly Perl-isms are also part of its strength), so this makes a lot of sense, and may yet drag Ruby in to the real world. Gemstone gets bonus points for providing yet another example of confusing efficiency with scalability.

BTW: Mike came up with a great acronym for Gemstone to use: GLARE: “Gemstone Linux Apache and Ruby Emulation”.

UPDATE: Avi caught me red handed for not reading the entire interview. Upon further reading of the interview and Avi’s excellent blog posting comparing Gemstone to Rails, it appears the Gemstone folks are very much talking about scalability as opposed to efficiency. In fact, it seems they are expecting the primary advantage of MagLev to be through Gemstone’s persistence architecture (here’s hoping it is also a lot more efficient).

SCALE and Zumastore 2

Posted by Christopher Smith Sun, 11 Feb 2007 22:08:00 GMT

I’m spending this weekend at SCALE. As always, the conference is great, and better than the year before. The talks are spilling out in to the halls, often multiple talks at a time (right now Chris DiBona’s talk has so many people attending and the spill over is so great, that it makes more sense to catch the mp3 of it at a later date).

One of the coolest things so far was my friend Daniel Phillips’ announcement of the Zumastor project. It looks like this Google sponsored open source project is finally going to give Network Appliances some real open source competition.

I was intrigued by a presentation on SystemTap. This is the first system I’ve seen that looks like it can give DTrace a run for the money, and most importantly it runs on Linux. It isn’t all there yet, but it’s close enough I’m going to start playing with it.

I was also impressed to see the Squeak folks making an appearance, both with a booth and a BoF later tonight. Looks like that project still has a decent amount of momentum.

Sun had a presentation talking about their open source stack (software and hardware). It was fun listening to just how much Sun gets the message that just five years ago I thought was falling on deaf ears there. It was also neat seeing a graph from a study that was done showing who was contributing to open source. Sun is the clear leader in terms of the amount of code and total man hours they’ve contributed (multiples of what most others have done). People don’t always grok that.

UPDATE: Found the study on who contributes to open source. Thanks to Matt Ingenthron (who did the presentation at SCALE) for getting me a pointer even before his slides make it out to the SCALE web site.

problem isVisualWorks ifFalse: [Gentoo] 1

Posted by Christopher Smith Mon, 02 Oct 2006 02:23:00 GMT

After posting about my problems getting Cincom Smalltalk to work on my Gentoo system, I recevied an impressive amount of help. Aside from my friend the committed Smalltalker, I also received help from Isaac Gouy (who was able to quickly demonstrate that Cincom worked just fine with glibc 2.4), and most impressively James Robertson, the product manager for Cincom Smalltalk. I got all this help despite being too lazy to post to the appropriate mailing list or contact Cincom’s technical support. It’s nice to know the product is supported this fervently.

I sent Mr. Robertson my strace, showing VisualWorks doing the mmap() tango indefinitely. However, he had asked for a core file and I realized I didn’t have one. So, I set about creating one for him. I adjusted ulimit and launched VisualWorks…. and it just worked!

The main thing that has changed since the last time I launched it was that Gentoo had an update to glibc, so while I have no concrete evidence (which obviously didn’t prevent me from pointing an accusatory finger in VisualWork’s direction ;-), my prime suspect is some kind of bug in Gentoo’s glibc.

Honestly, I’m just happy to have VisualWorks working on my system, and my general laziness will prevent me from investigating this further. It is snappier and generally more consistent with the rest of my development tools, so it’s much more fun to work with than Squeak.

Don’t get me wrong: I still really like Squeak, and in particular I like how it is open sourced, but Squeak’s UI really annoys the heck out of me, and I really do prefer to have VisualWork’s more efficient runtime. At some point I’ll be annoyed by Cincom not being truly open source, but for now I’m enjoying it tremendously.

Ruby On Nails Scratching a Chalkboard 52

Posted by Christopher Smith Tue, 12 Sep 2006 17:59:00 GMT

So, as I explore how Ruby works, I’m discovering some bits of ugliness. It’s syntax is increasingly reminding me more of Perl than Smalltalk. A case in point: blocks.

I’d heard so much about Ruby’s Smalltalkishness that I was a bit taken aback when I saw control statements in the language grammar. In Smalltalk, control flow is managed using methods and blocks, and I knew Ruby had blocks (this is one of the things that you hear so much about in Beyond Java), so why did they need these control statements? In Smalltalk, control flow looks like this:

1 + 1 = 2
  ifTrue: ['it is true']
  ifFalse: ['it is false']

Now, I can’t claim that this provides any real productivity boost over Ruby’s approach:

if (1 + 1 == 2) then
  'it is true'
else
  'it is false'
end

But I was kind of surprised, given Ruby’s ties to Smalltalk, that someone hadn’t hacked it in. So, I went about hacking it in myself. That’s when I found out why.

It turns out that blocks in Ruby have a very high level of syntactic sugariness. Not only do they have their own special literal form (which is a key advantage over say Java’s Inner Classes, or C++ functors without boost::lambda), but they also have their own special status which really makes them non-objects. (I found it amusing to discover that the most non-object entity in Ruby is a block).

Here’s the magic: blocks aren’t passed as normal parameters to functions. They are passed through an implicit variable (showcasing Ruby’s Perlishness here). So, if, for example, I wanted to add something like Smalltalk’s ifTrue: to Ruby, I’d do the following:

class TrueClass
  def ifTrue
      yield
  end
end

class FalseClass
  def ifTrue
  end
end

(1 + 1 == 2).ifTrue { puts 'Math works' }
(1 + 3 == 2).ifTrue { puts 'Math is broken' }

Notice that ifTrue doesn’t appear to take any parameters, and neither does the “yield” method. In reality, the block is an implicit parameter. One Ruby tutorial claimed this is a good thing, because it means that all Ruby methods can take a block as a parameter…. even if they don’t use it. Me, I’m a big fan of explicitness, but I can see that in a scripting world, sometimes these kind of shortcuts are nice to have. What’s bad about this is that not only does it mean that all Ruby methods can take a block as a parameter, it also means all Ruby methods can only take exactly one block as a parameter, and it has to be the last one.

Now, it turns out that Ruby has a wrapper around blocks called Proc, which lets you treat a block like a real object, Of course, it has all the syntactic beauty of Java’s Inner Classes. Here’s how you can do ifTrueifFalse in Ruby:

class TrueClass
  def ifTrueIfFalse(trueProc, falseProc)
    trueProc.call
  end
end

class FalseClass
  def ifTrueIfFalse(trueProc, falseProc)
    falseProc.call
  end
end

(1 + 1 == 2).ifTrueIfFalse(Proc.new { puts 'Math works' },Proc.new {puts 'Math is broken'})

But wait! There’s more! Since Proc’s are proper objects, you can query them for meta-information, which is really handy for various dynamic programming tricks. Only… Ruby’s interface is kind of weird. Proc’s have this method “arity” which tells you how many arguments the block takes… sort of. For reasons passing understanding, if a block takes zero arguments, the function returns “-1” intead of “0”, and if it takes 1 argument, it returns “-2” instead of “1”. So, now we’ve established that it can never return 0 or 1, and that you can’t always use the return value as an collection size for your argument list. Here’s where it gets really crazy though: if your function takes a variable argument list with it’s last parameter, arity returns “0 - # of args”. So, quick question for you: if arity returns back -2, does that mean it’s argumetn list is one argument long, or that it takes one argument followed by a variable list of arguments? I’m not sure how Bruce Tate can claim that Ruby doesn’t have some weird anachronisms that get in the way of doing metaprogramming with a straight face.

In fairness, the case where you want to pass a single block as your last argument seems like the common case, and Ruby is a scripting language after all. I’m mostly annoyed because I’ve heard so many people talk about Ruby’s elegance, comparing it favourably with Smalltalk (which admittedly is not entirely without warts). Upon inspection it seems to have warts just like other languages (well, some languages have a few more warts than others). Still, there is hope. Ruby does seem to have some genuinely nice features, and it is open source, so there is always the possibility that some of these idiosyncracies will get cleaned up in the future.

UPDATE: So, someone with some real Ruby experience has clarified for me that nobody actually does “Proc.new” in Ruby. Instead they use Lambda. So, invoking my ifTrueIfFalse method would normally be done like so:

(1 + 1 == 2).ifTrueIfFalse(lambda { 'Math Works' },lambda {'Math Doesn't Work' })

Which I have to admit does seem a lot prettier for some reason.

ANOTHER UPDATE: I’ve gotten some great comments to this article, and I thought I should incorporate their content. First, people have suggested that you can break up ifTrueIfFalse in to two calls that are chained together, and then get back some of the elegance. I thought about this when I first looked in to it, but you lose the ability to pick up a return object cleanly.

Antti Tarvainen provided some excellent points. In particular he clarified the difference between a Proc that takes no arguments (arity returns 0) and a Proc that doesn’t define any arguments returns -1. Furthermore, arity has been updated for Ruby 1.9 to what seems like a more sensible behavior. I noticed that even in 1.8

puts lambda {|a|}.arity
returns 1, which suggests the Ruby documentation is a wee bit out of date.

I still think it’d be far more sensible to not overload the arity method and instead have numArgs? which gets you the number of required arguments”, hasOptional? which gets you back a boolean as to whether there are optional arguments, and argsDefined? which gets you back a boolean as to whether the Proc has defined arguments at all. Overloading the meaning of the return value just results in more code that needs to check for special cases and cases where you can’t actually know which of two states is correct.

Also, there seems to be confusion about my point in comparing it to Smalltalk’s ifTrue:ifFalse:. Of course one should use Ruby idioms when doing Ruby. The ifTrue:ifFalse: example is just a simple and well understood example of having more than one block in your parameter list. I will say that there is a certain kind of semantic elegance that comes from having all your control flow done through methods and objects. Ruby advocates always say that in Ruby “everything is an object”, but it appears that blocks and control flow expressions are not, and in this regard Ruby doesn’t quite live up to expectations set by Smalltalk and LISP.

Cincom Smalltalk + glibc-2.4 == hang 6

Posted by Christopher Smith Mon, 11 Sep 2006 05:22:00 GMT

So, all this Ruby-ing has made me yearn for Smalltalk. Accordingly, I started trolling for Smalltalk implementations. Squeak is working well as always, but Cincom is available for free, so I thought I’d give it a whirl. Just one catch: Cincom’s VM appears to rely on Linuxthreads, and won’t work on NPTL. This is a pitty as the latest glibc (2.4) no longer supports Linuxthreads.

One more cheer for open source software!

My First Ruby Program

Posted by Christopher Smith Sun, 10 Sep 2006 05:43:00 GMT

I realized that earlier today I wrote my first Ruby program, and it’s probably worth documenting this moment for posterity.

It’s a trivial bit of code:

Fixing Typo sequence numbers
require 'postgres'

sequences = [
  'blacklist_patterns', 'blogs', 'categories',
  'contents', 'page_caches', 'pings',
  'redirects', 'resources', 'sessions',
  'sidebars', 'tags', 'text_filters',
  'triggers', 'users'
]

def fixSequence(db,tableName)
  results = db.query("select max(id) from #{tableName}")
  max_id = results.first.first
  if max_id then 
    db.exec("select setval('#{tableName}_id_seq'::text,#{max_id});").clear
  end
end

db = PGconn.connect("localhost", 5432)
sequences.each {|sequence| fixSequence(db,sequence)}
db.close()

So far, my first impression is that Ruby tries to be like Smalltalk, but is Perlish enough to fall short IMHO. Of course, I hardly know the language yet, so there may be a more elegant way to do things that I have yet to uncover. In particular, I’m wondering why the True and False classes don’t have “ifTrue:ifFalse” type methods that take blocks as arugments. Seems like an obvious “nice to have”. IIRC it’s possible to add methods to existing classes, so maybe I can do this to keep the Smalltalk cravings to a minimum.