Big Dave on Video

Posted by Rick DeNatale Wed, 30 Apr 2008 02:24:00 GMT

InfoQ recently published a video interview with Dave Thomas (of OTI fame).

In his inimitable style, Dave covers lots of interesting topics in software development, both today and with a historical perspective.

I agree with almost everything he says, and find the rest food for thought.

His comments about Java as a platform are quite germane to the article I published yesterday. If you’ve been exposed to Big Dave before, you’ll enjoy this, and if you haven’t it’s a good introduction.

Tags , , , ,  | 1 comment | no trackbacks

The Perils of Ruby

Posted by Rick DeNatale Sun, 27 Apr 2008 19:17:00 GMT

Charlie Nutter just published an article which assesses the various implementations of Ruby. In all it’s a quite even-handed description coming from one of the main proponents of JRuby.

Charlie talks about each implementation and describes the perils each faces.

These seem to be days of crisis for Ruby. With so many implementations compatibility is a challenge. Particularly since Ruby lacks a formal specification. The Rubinius developers have been working hard to address this by developing, RubySpecs, a set of rspec style specifications for Ruby. Matz has also convened a regular meeting of Ruby implementors via irc. The first meeting took place last week,and one of the decisions taken was to make RubySpec the officially blessed set of tests to be used by all implementors.

Compatibility is hard. I’m not talking a little hard, I’m talking monumentally hard. Ruby is a very flexible, complicated language to implement, and it ships with a number of very flexible, complicated core class implementations. Very little exists in the way of specifications and test kits. – Charles Nutter

Is Ruby Forking?

Currently there are two major “official” versions of Ruby. Ruby 1.8, which is in use for most production purposes, and Ruby 1.9 which introduces new features (e.g. integrated support for strings with different encodings), new language features (e.g. new syntax for hash literals which allows actual parameters to methods taking an options hash as the last argument to look like keyword parameters), and some incompatibilities.

As Charlie points out the peril here is that Rubyists have a hard time figuring out which Ruby to target. Ruby 1.9 isn’t yet ready for production, but even when it is, will the advantages outweigh the cost of the ‘porting’ needed to get past the incompatibilities.

Some implementations are attempting to bridge the gap. JRuby is taking on some 1.9 features while maintaining compatibility with 1.8. The recent preview release of Ruby 1.8.7, also introduces some 1.9 features to the 1.8.x code base, albeit with some initial incompatibilities, which hopefully will be worked out. RubySpec should help this.

MacRuby, on the other hand, is taking another approach to 1.9 features. MacRuby is a new Apple implementation of Ruby which uses the Objective-C run-time as a platform, much as JRUby and IronRuby use the Java JVM, and Microsoft DLR, as platforms.

One of the ways in which MacRuby exploits 1.9 is the way they are mapping the new hash literal syntax I just mentioned. Let’s look a bit at that new syntax.

At the risk of offending the “Rails isn’t Ruby crowd”, I’m going to take an example from ActiveRecord, because Rails tends to use option hash parameters quite a bit. In Ruby 1.8 I might code:

Book.find(:all, :order => "title ASC", :limit => 10)

To get the first 10 books sorted by title. The new Ruby 1.9 syntax allows this to be written alternatively as:

Book.find(:all, order: "title ASC", limit: 10)

Which is actually an identical call. These “keyword arguments” are quite reminiscent of the Smalltalk-inspired syntax used in Objective-C. As I understand it, MacRuby will look at such a call, and turn it into an Objective-C message internally something like:

[Book find: @selector(all) order: "title ASC" limit: 10]

But this isn’t exactly the same. In Ruby one method can handle multiple optional keyword arguments which can appear (or not) in any order. In Objective-C the message selectors find:order:limit, and find:limit:order would map to different methods. When I asked Laurent Sansonetti about this on ruby-core, he said that the implementation would actually determine whether the receiving object understands :find:order:limit: and if not fall back to a more ruby-like call. I’m not sure how such a chicken-typed implementation will really stand up in practice, but I guess that time will tell.

I’m also not sure what the long-term implications of this are as Matz moves from 1.9 to 2.0 and perhaps starts defining new method definition syntax which provides syntactic sugar (at least) for handling “keyword parameter” hashes on the other side of the invocation.

Platforms, Platforms, Platforms

As I said above, one way to characterize the various ruby implementations is by the platform each ‘advocates’. Traditional MRI Ruby, and Ruby 1.9 run well on UNIX like platforms like Linux, OS X, and Solaris. Rubinius is building a new Ruby-based platform using ideas from Squeak and earlier Smalltalk implementations, although as far as I can tell, it’s not following the Smalltalk philosophy of being an “operating system” on its own, IronRuby is really an attempt to optimize a Ruby implementation for Microsoft Platforms, while JRuby leverages the JVM.

I can’t help but think back to the early 1990s as a member of the Smalltalk community. Smallalk had gained a fair bit of traction in the enterprise, particularly in industries such as finance and insurance where rapid application development was important. Java started to take the wind out of Smalltalk’s sails. I always considered the switch from Smalltalk to Java to be driven by factors such as the cost of entry for an individual programmer, but my old friend Dave Thomas (OTI’s BigDave, not pragDave) points out that it was more a matter of companies like IBM (one of the main Smalltalk vendors by then) moving to Java as an anti-Microsoft platform. Java really took off in the enterprise after IBM, Sun, and others entered a kind of ABM treaty (Anyone But Microsoft)

Ruby is in a different place than Smalltalk was at that time. Smalltalk was available from, and advocated by, a small number of vendors who sold it at a handsome price. Two of the big Smalltalk implementations survive, IBM/VisualAge Smalltalk is still available from Instantiations at a four figure price. Cincom sells the latest version of VisualWorks Smalltalk, under a complex web of licensing options. Both of these “compete” with the open-source Squeak implementation.

The environment has shifted out from under the big corporate providers of software development tooling like IBM, Sun and Microsoft. It’s hard to see how to make big bucks selling development tools when so much is available under various open-source licenses for the cost of a download.

Ruby has come out of today’s open-software environment. It was conceived out of one man’s desire for a language which he personally found pleasing, and grew within the open source community. While I applaud and appreciate the support that Ruby has received from Sun, Microsoft, Apple, and other corporations, I can’t help but feeling that some of the motivation is based on keeping control of the platform.

These might be perilous times for Ruby, but I’ve got confidence that the overall community will keep things from getting too far out of whack.

Again, time will tell.

Posted in  | Tags  | 7 comments | no trackbacks

x ||= y, Redux

Posted by Rick DeNatale Sat, 26 Apr 2008 15:11:00 GMT

A while back there was quite a thread on the Ruby-lang mailing list about the real semantics of the expression.
a[x] ||= some_value

In many books and articles on Ruby the form:

a <op>= b

Where <op> is an operator like + Is described as syntactic sugar:

a = a <op> b

While this is true in most cases, it isn’t’ true if the operator is ||.

This comes to light when the left hand side is a method call, to an accessor, or accessor-like method. For example

h = Hash.new("hello")
h[:fred] ||= ""
h #=> {}

Some find it surprising that the assignment doesn’t cause the hash to have :fred as a key. What this code snippet shows is that the assignment doesn’t actually assign anything if the left hand expression returns a logically true value. A Hash with a default value will return the default value when accessed by any key which is not present in the hash. Since h[:fred] returns the default value, the assignment doesn’t happen.

This affects any object which has ‘accessor’ methods. Here’s a class cooked up just to explore this aspect of Ruby.

class ChattyCathy

  def initialize(x=nil)
    @x = x
    puts "created x is now #{x.inspect}"
  end

  def x
    puts "x read x is #{@x.inspect}"
    @x
  end

  def x=(val)
    puts "x written, now #{val.inspect}"
    @x = val
  end
end

The purpose of this class is simply to let us see exactly when the x attribute is read and written. Now if we run this code

c = ChattyCathy.new(42)
puts "about to evaluate c.x ||= 43"
c.x ||= 43
c = ChattyCathy.new
puts "about to evaluate c.x ||= 43"
c.x ||= 43

We get the following output:

created x is now 42 about to evaluate c.x ||= 43 x read x is 42 created x is now nil about to evaluate c.x ||= 43 x read x is nil x written, now 43

Which clearly illustrates just when the assignment actually happens.

The real expansion of x ||= y

Matz explains that the real expansion of x ||= y is:

x || x = y

The expectation that x ||= y is the same as x = x || y, does seem reasonable to someone ‘coming from’ C or one of it’s derivative languages. As far as I can determine, C introduced the notion of assignment operators like += and -=. And K&R defined these assignment operators as a shorthand for x = x + y, etc.

On the other hand, although C has logical operators || and && which, like Ruby have ‘short-circuit’ evaluation, it doesn’t allow ||=, or &&= as assignment operators.

Since || is a ‘short-circuit’ boolean operator, the left hand operand expression is only evaluated if the right hand operand expression evaluates to a logically false value, i.e. either nil or false.

The way that Matz included ||= as an assignment operator makes perfect sense to me. The ||= assignment operator reserves the short-circuit nature of ||.

So what about x &&= y

Although I haven’t seen this discussed anywhere, &&= in Ruby has similar behavior:

c = ChattyCathy.new
puts "about to evaluate c.x &&= true"
c.x &&= true
puts "about to evaluate c.x = \"hi\""
c.x = "Hi"
puts "about to evaluate c.x &&= true"
c.x &&= true
created x is now nil about to evaluate c.x &#38;&#38;= true x read x is nil about to evaluate c.x = &#8220;hi&#8221; x written, now &#8220;Hi&#8221; about to evaluate c.x &#38;&#38;= true x read x is &#8220;Hi&#8221; x written, now true

So the expansion of x &&= y is x && x = y

Posted in  | 5 comments | no trackbacks

It's About Time!

Posted by Rick DeNatale Wed, 23 Apr 2008 20:17:00 GMT

The third edition of Agile Web Development With Rails is now in Beta.

Sam Ruby has become the third author, along with Dave Thomas and DHH. According to PragDave, Sam has converted the Depot App tutorial to be compatible with Rails 2, and the rest of the book is also being revised.

Posted in  | no comments | no trackbacks

Rails Integration Test File Upload Plugin

Posted by Rick DeNatale Fri, 18 Apr 2008 22:07:00 GMT

Some time ago, I wrote a rails patch which allows http file uploading in integration tests.

You just use the same TestUploadedFile class used in functional tests or controller specs if you’re an RSpec’er. So you can do something like.
    post '/upload' :file => TestUploadedFile("/path/to/blah.txt")

The patch detects a TestUploaded file amongst the parameters, and converts the request into a proper multi-part request.

It will work for both posts and updates.

If you’re running edge rails you’ve already got this. But many have asked for a version for earlier rails versions. At work, I’ve been working on an RSpec story which requires file uploading, and we’re using the 2.0.2 gem version of Rails for deployment purposes, so I whipped up a little plugin which patches 2.0.2 Rails with the changes from Rails changeset 8978. The plugin checks the rails version and throws an exception if it’s anything other than “2.0.2” since I haven’t tried this with anything earlier, and it’s not necessary for anything newer.

You can get it from git hub at git://github.com/rubyredrick/integration_upload_plugin.git

This also marks the first time I’ve used git for anything but gitting Rubinius.

Posted in  | Tags ,  | no comments | no trackbacks