In Ruby Globals, Aren't Always Global

Posted by Rick DeNatale Mon, 17 Nov 2008 20:00:00 GMT

Ola Bini, just wrote about how he’s planning to have a special variable to expose the result of a regular expression match in his new language Ioke.

The idea is to introduce a special variable called it, which holds the result of the conditional expression in an if or unless statement, or method in Ioke’s case. Ola says that this is different from the special Ruby globals like $~ because For one, it’s not a global variable. It’s only available inside the lexical context if an ‘if’ or ‘unless’ method. It’s also a lexical variable, meaning it can be captured by a closure. And finally, it’s a general solution to more things than the regular expression problem.

As it turns out, I learned at RubyConf that the Ruby ‘globals’ which give access to the results of the last regular expression match, aren’t really globals at all. This came up in a conversation after the MagLev presentation, when Charlie Nutter asked Allen Otis of Gemstone how they were handling those variables, since they are really frame locals. Matz was standing there and quickly confirmed Charlies observation.

So $~ and it’s friends, like $1, are really more like special names for local variables. Other than the lexical ‘look’ they behave more like locals than globals.

I just concocted a completely bogus Ruby program to demonstrate this.

def lambdas(str, re)
   re.match(str)
   [lambda {$~}, lambda {|str| re.match(str)}]
end

m_lambda, match_lambda = *lambdas("this", /(this|that)/)
puts "(m_lambda.call)[1] is #{(m_lambda.call)[1].inspect}"
/(foo)/.match("foo")
puts "$~[1] is #{$~[1].inspect}"
puts "m_lambda still is #{(m_lambda.call)[1].inspect}"
match_lambda.call('that')
puts "now m_lambda is #{(m_lambda.call)[1].inspect}"
puts "$~[1] is still #{$~[1].inspect}"

The lambdas method returns two lambdas, the first simply returns the current value of $~ when evaluated, the second does a match against the regular expression passed into the lambdas method with a new string, on demand.

When run this produces the following output:

(m_lambda.call)[1] is "this"
$~[1] is "foo"
m_lambda still is "this"
now m_lambda is "that"
$~[1] is still "foo"

Note that $~ in the outer context is a different variable than $~ in the context of the invocation of the lambdas method. Let’s call these the outer and inner $~ variables respectively. Doing a regular expression match in the outer context leaves the inner $~ unchanged, while calling the second lambda affects the value of the inner $~ but leaves the outer $~ unchanged.

As they say, you learn something new every day.

Posted in  | 4 comments | no trackbacks

A Personal RubyConf 2008 Recap

Posted by Rick DeNatale Tue, 11 Nov 2008 01:11:00 GMT

RubyConf 2008 has come and gone. It was a great opportunity to meet Ruby friends and make new ones.

I think that my talk on Friday afternoon went well. It’s amazing how your perception of the conference changes when you shift from fretting about your upcoming talk, to relief once it’s done. I don’t know how many times I’ve given talks to similar audiences, but the butterflies never seem to stay away, and I think that it’s a good thing since it keeps you on your toes. If you are going to be in western Michigan on the evening of November 25th, I’ll be reprising this talk at XP West Michigan.

A Quick Sample of RubyConf 2008 Speakers

Greg Pollack has put up a preview of his upcoming “RubyConf Trailer” RubyConf in 90 Seconds. As he did earlier for this year’s RailsConf Gregg did brief video interviews of as many conference speakers as he could. He’s planning to edit these together, and provide them as kind of a video “Table of contents” to the full talk videos which will be appearing on the Confreaks web-site. Coby Randquist of Confreaks told me that he expected all the videos to be available by a week from today.

A Walk Down Memory Lane

Josh Susser, who is another Rubyist with a background in Smalltalk, tweeted during my talk, that I was “taking a walk down memory lane.” In a way, RubyConf 2008 was very much a walk down memory lane for me. Not only did I reminisce in my talk, but I got to see some old familiar faces from the early days of OOPSLA in the 1980s and 1990s. Allen Otis, who served as the technical half of the team from GemStone presenting MagLev was one. Another was Monty Williams, also of GemStone. I had a very nice lunch with Monty and his wife on Saturday, along with another more guy who had recently joined GemStone to work on MagLev, who we probably bored with old war stories.

Things I learned at RubyConf 2008

In no particular order:

  • Werewolf fever seems to have died off. As far as I could tell, no werewolf games materialized. The two main instigators weren’t there. Marcel Molina, apparently never was coming, and Chad Fowler, unfortunately, had to stay away due to the sudden death of his father-in-law. On the other hand, the musicians, some of them former werewolves, were there in force, leading to an enjoyable jam session.

  • Jim Weirich and I established that I’ve got a year or two on him, although my hair has retained a bit more of its color.

  • I also found that I wasn’t the oldest attendee, but I won’t reveal his or her identity.

  • “PragDave” Thomas gave a great talk, challenging the community to “fork Ruby”, that is to spawn some incubator branches of the language to experiment with new ideas without delaying or derailing the main Ruby language. If some of these forks produced value, they might have their ideas merged back. Some of his ideas for forks were Ruby-lite, which had lots of cruft which is not often used removed. Another was Otuby (for optionally typed Ruby), which was different from Charlie Nutter’s Duby

    I thought that the most interesting was probably Cluby, or Ruby with Closures. By making some lexical changes to the language, Dave suggested that Cluby could allow blocks to always be lambda literals, and to allow blocks to be used in many more places, such as for ANY argument to a method. This would allow control flow to be implemented by methods, for example an if method which took an argument to be tested, and one or two blocks, to be executed depending on the truthiness of the first argument, or a looping method which evaluated it’s second block argument as long at the first block argument evaluated to a truthy value. He also did away with grammar for both method definitions and class/instance variables. Methods would simply be blocks which would be called when the object received the corresponding method selector in a message.

    He acknowledged, that “Smalltalk had already done this.” Which is half-true. Smalltalk alows arbitrary block closures as arguments, but you need to look at a language like self for the unification of methods and attributes.

  • There are some talented musicians in the Ruby community. This wasn’t surprising since there seems to be a positive correlation between talent for programming and talent for music. Jim Weirich is an avid, and accomplished guitarist, and David Chelimsky and Diego Scataglini blew me away with a cool acoustic jazz guitar duet! I gotta give those guys, some RSpec!

  • Appropriately enough, since we were so close to Epcot, once again I learned that “it’s a small world after all.” My wife was along with me, although she didn’t hang out at the conference. On Saturday evening, Deborah and I tagged along with a group which included Matz and the members of his team who were there as well as a few of us gai-jin. Deborah is half-Japanese, an Air Force brat who spent a couple of tours of duty in Tokyo during her formative years. She sat next to Matz and they talked a lot in both Japanese and English. At one point Deborah was telling Matz about some of our Japanese IBM/ex-IBM friends. When she mentioned Kuse-san, who had visited with us several times when he was here on business, Matz said “I know Kuse-san!” In retrospect this isn’t surprising, since Kuse-san, now the director of IBM’s Tokyo Research Lab, has a background in object oriented languages.

And to put a cap on a week full of personal memories, Deb and I flew back home on Sunday for an evening from the 1960s with Ed Sullivan, old VW ads, and the “Beatles.”

Posted in ,  | Tags  | 4 comments | no trackbacks

Radiant Sprint

Posted by Rick DeNatale Wed, 29 Oct 2008 20:59:00 GMT

Last weekend, Sean Cribbs, ran a Radiant Sprint in Carrboro, NC, to press for a new release of the Radiant CMS.

I had this in the back of my mind, but hadn’t put it on my calendar. So when Marc Imbriaco tweeted that he was going there, I decided to hop in the car and drive the 45 miles and help out.

It’s always great to have an opportunity to work with guys you haven’t worked with before. I ended up pairing with Sean on refactoring one of he main controllers to be restful. I tried to follow him as he worked on the views (which use HAML), and I think I was much more useful when we actually got to changing the Ruby code.

If you are interested in finding out more about what transpired, here’s a great summary of the event

Posted in ,  | Tags ,  | no comments | no trackbacks

Solving the Final Google Treasure Hunt Problem in Ruby

Posted by Rick DeNatale Sun, 08 Jun 2008 01:43:00 GMT

For the past four weeks, Google has been running the 2008 Google Treasure Hunt. Each Monday a new question was asked, requiring a ‘simple’ answer. Actually, each question was parameterized, and the parameters were ‘randomly’ generated for each participant.

For each of the four questions, I wrote a Ruby program to find the answer.

The final question was probably the hardest, and although it’s still ‘alive’, the spoilers have already started to appear on the internets. Peter Krumins has posted a solution using unix shell commands, so I figured I’d show my Ruby solution

The Problem

As Peter describes the problem is to find the smallest prime number which can be expressed as a sum of several different numbers of consecutive primes. Here’s the question as Google posed it to me:

Find the smallest number that can be expressed as

the sum of 3 consecutive prime numbers,

the sum of 5 consecutive prime numbers,

the sum of 275 consecutive prime numbers,

the sum of 1167 consecutive prime numbers,

and is itself a prime number.

For example, 41 is the smallest prime number that can be expressed as the sum of 3 consecutive primes (11 + 13 + 17 = 41) and the sum of 6 consecutive primes (2 + 3 + 5 + 7 + 11 + 13 = 41).

Note that I’ve got a different set of four numbers of consecutive primes than Peter’s

The Approach

I always try to do ‘the simplest thing that could possibly work.’ Like Peter I had no desire to write a prime number generator. A little googling found me the same source of prime numbers. I figured as a first guess that the answer would probably lie somewhere within the first million prime numbers, so I downloaded that list, and examined the list in Textmate.

As Peter notes, the file has two lines of header, and then several primes in sequence on each line. I just deleted the header lines in Textmate and then wrote a class which would read the file and return each prime number in sequence:

class PrimeReader
  def initialize(file)
    @file = file
    read_line
    yield self
  end

  def next
    read_line if @numbers.empty?
    @numbers.shift.to_i
  end

  def read_line
    @numbers = @file.readline.split(' ')
  end
end

This should be fairly explanatory. PrimeReader reads the file as necessary and hands out each prime number.

Now that I had a source of consecutive primes it was time to write the code to search for the answer. Here’s the outer loop:

processor = Processor.new

File.open("#{File.dirname(__FILE__)}/primes1.txt") do |f|
  PrimeReader.new(f) do | primes |
    until processor.test(primes.next)
    end
  end
end

The real work is done, in the unimaginatively named Processor. The loop reads lines from the PrimeReader until the processor finds the desired prime or end of file generates an exception.

And here’s the Processor class:

class Processor
  def initialize
    @counts = [3, 5, 275, 1167].reverse
    # @counts = [3,6]
    @sums = @counts.inject({}) { |hash, count| hash[count] = []; hash}
    @processed = []
  end

  def test(prime)
    puts "testing #{1+@processed.length}: #{prime} "
    qualifies(prime) || process(prime)
  end

  def qualifies(prime)
    @sums.each_value do | sums |
      return false unless sums.include?(prime)
    end
    report(prime)
    true
  end

  def process(prime)
    @processed << prime
    @counts.each do |count|
      calc_sum(count)
    end
    false
  end

  def calc_sum(count)
    if @processed.length >= count
      @sums[count] << @processed[-count,count].inject(0) { |sum, p| sum + p}
    end
  end

  def report(found)
    puts "Found #{found}"
    @counts.each do | count|
      report_sum(count, found)
    end
  end

  def report_sum(count, found)
    sums = @sums[count]
    sum_start = sums.index(found)
    puts "#{found} = #{@processed[sum_start, count].join(" + ")}"
  end
end

The approach I took was to compute the sums and save them in arrays which in turn are the values for each count used as a key in the hash @sums. I keep each prime in the array @processed which is used to calculate the sums.

I hard coded the parameters in the initialize method, note the commented out assignment to counts, by changing the commenting I could test the code against the example given and show that my code found 41 as the lowest prime expressible by both 3 and 6 consecutive primes.

The test method reports the number and value of each prime it examines, purely as a ‘progress indicator.’ The statment “qualifies(prime) || process(prime)” will return true if qualifies returns a truthy value, otherwise it will invoke process which always returns false.

The qualifies method returns true only if the array for each count contains the current prime, which is the essence of what we are seeking. Otherwise it returns false.

The process method first appends the new prime to @processed, then calculates the sum for each count using the calc_sum method. This method determines if we have enough primes in @processed to calculate the particular sum, and if so calculates the sum and appends it to the array for the count.

Once the answer has been found, the report method prints it and the sums which total to it. The sums are calculated in the report_sum method. This method takes a slice out of the @processed array, consisting of the count elements starting at the index where the answer is found in the particular sums array. A bit of reflection will reveal that this is precisely the primes which add to the answer.

In the case of my parameters, the answer, in case you are wondering is 5,181,901, which was confirmed by Google when I gave my answer. This is the 360,245th prime number by the way.

Performance

Although this might be a bit of a brute force approach, the performance was acceptable.

The biggest feature of Ruby which makes this approach feasible is the copy-on-write nature of Ruby arrays. In Ruby Array#slice (a.k.a. Array#[]) doesn’t copy the elements of the array, it just creates a new Array with an offset from the beginning of the original array and the length of the result. As long as neither Array is changed to affect one of the shared elements, nothing is copied, but when a shared element in the source or result array is changed, Ruby first does the copy to preserve the semantics.

My code does a lot of slicing of the @processed array, but other than appending to the end of the @processed array, the accesses to that array and the slices are read-only, so nothing needs to be copied.

Posted in  | 7 comments | no trackbacks

What Would You Miss If You Had To Stop Using Ruby and Go Back to Smalltalk?

Posted by Rick DeNatale Wed, 21 May 2008 20:58:00 GMT

Last night, James Robertson from Cincom, presented Smalltalk and Seaside to the Raleigh Ruby Brigade.

It was an interesting deja-vu experience, since in my younger days, part of my job with IBM was evangelizing Smalltalk, much as James does today. It was interesting to see what has and hasn’t changed. For the most part the things about Smalltalk which were blessings and curses (or many times both) haven’t changed. The IDE is still powerful. It gets much of it’s power from Smalltalk’s model of how source code and run-time implementation objects like compiled-methods, classes and metaclasses interact, but the consequence is that there aren’t really Smalltalk source files to use with popular editors like VIM or EMACS or Textmate. The question came up about whether the Smalltalk IDE supported the notion of giving the code to an external editor, and the answer was that the size of a typical Smalltalk method, which is the unit of editing, was so small (10 lines is a long Smalltalk method) as to make it ‘moot.’ I used to get the same kind of questions and give pretty much the same answers.

One area where Smalltalk really does excel is in it’s debugging and inspection tools. The same implementation object model which enables browser features, like finding all senders or implementers of a message using structural rather than textual searching, also allows live debugging, where you can not only inspect the run-time state at a breakpoint, or when an exception occurs, but actually make changes to the running code, and compile those changes, at which point the VM prunes the invocation stack down to the point of the change and allows you to restart from that point. Protestations from TDD/BDD adherents that you don’t need no steenking debugger if you follow TDD practice, the Smalltalk debugger was tool much favored by the very people, like Kent Beck, who invented TDD. Many Rubyists who were around for more than a year or two had an anti-debugger attitude, generated more, I suspect, by the lack of a decent Ruby debugger than any real hatred of debuggers.

Now that ruby-debug has been around for almost two years, the situation is much better. Ruby has a fairly competent debugger which allows stepping through code. It’s still hampered by Ruby’s rather simple run-time meta information, being forced to work on a line-by-line mode, rather than being able to step through individual expressions as can the Smalltalk debugger. And we’re still a long way from the live surgery capabilities I described. Perhaps as Ruby VM implementations mature we might see some of these advanced features emerge, perhaps this is something which the Rubinius implementers might also take as an inspiration from Smalltalk. This is one of the main things I miss from my Smalltalk days.

On the other hand, at this point in time, I’m really much happier working in Ruby than I think I would be were I somehow forced to work in Smalltalk again instead. Much as I love it, Smalltalk is now my second favorite language.

At one point last night, Brian Adkins asked me the question which is the title of this article. I think it’s a fair question, and I’m not sure I know exactly, but let me try to answer it.

What I’d miss from Ruby

I’ve said this before, but one of the things I like about Ruby is that it is more dynamic than Smalltalk in ways which I like, and cuts back on other aspects of Smalltalk which I don’t think are really that important.

One of the things I like about Ruby is the elimination of variable declarations. A good example of this was that during the Seaside demo last night, James showed how interfacing to the database requires attribute instance variables in model objects to be declared. Now the IDE provides tools for helping with this, you get prompted with a list of column names and can add them one by one just by clicking buttons. Contrast this with ActiveRecord where model objects just acquire instance variables dynamically at run-time. Now I know that some prefer more explicit mappings, but personally I feel that the dynamic mapping provides much more capability for much less ceremony.

The ways in which Ruby is more dynamic than Smalltalk seem to me to provide better facilities for building low-ceremony architectures and artifacts like Rails, Rake, etc. There are more dynamic languages than Ruby to be sure, such as Self, and from what I can sense JavaScript, but Ruby seems to strike a very nice balance.

Much has been made of the legacy of Smalltalk in pioneering metaprogramming, although some Lisp guys might quibble with that, and in truth, most Smalltalk metaprogramming was only used to support the IDE and never put to use by application programmers. Alan Kay used to say that he was disappointed that no one seemed to make new classes of Behavior (which is the superclass of both Class and Metaclass in Smalltalk). I know he said this to some of us at an IBM internal conference, which at least led to Dave Smith and Jerry Archbald developing a “behavior of behavior” tutorial which ran for several years at OOPSLA. But Rubyists have taken metaprogramming much further than I recall from my Smalltalk days.

On the other end of the scale, Smalltalk as James pointed out, as I used to, has a very simple syntax, a few reserved words (self, super, nil, true, and false), three types of messages (unary, binary, and keyword), two operators (:= for assignment, and ^ for return), and a few more things for defining block literals.

Now when I was doing James’ job, this got mixed reactions. Some people took to syntax like:

topLeft = Point x: 3+2*5 y: 15

While others found it just a little too strange, something which we Smalltalkers just couldn’t get.

Another thing which put off newcomers to Smalltalk was that, because of the simplicity of the language, and the lack of any form of operator precedence (remember the only operators are := and ^), that subexpression 3+2*5 evaluates to 25 and not 13.

Ruby trades off a little simplicity and does provide precedence between messages which seem like they should act as operators.

I’m not saying that Ruby is without quirks, just that different people react to different quirks in different ways. If you don’t like what you perceive to be the quirks of any programming language, you won’t be convinced, even by the most ardent supporter of those quirks.

One of the interesting effects of the Smalltalk syntax was that, as we observed back in Smalltalk’s heyday in the Enterprise (late ‘80s-early ‘90s), it seemed that a lot of COBOL programmers seemed to take to Smalltalk. We used to think that Smalltalk might actually become the 21st century COBOL, until the “Enterprise” got wooed away by EJBs and the like. The same things which made Smalltalk approachable by COBOL programmers made it seem weird to those who looked down on those COBOL programmers as “trade-school” programmers.

Another much-touted feature of Smalltalk, is that everything is done by message sending, even control flow. In Smalltalk a if/then/else control flow is achieved by sending an ifTrue:ifFalse: message to a boolean object as in:

 ^(x = 0) ifTrue:[a] ifFalse:[b]

Smalltalk evaluates this as if the the expression (x = 0) is evaluated by sending the message with the selector = and argument 0, to the object referenced by x. The result of that message, an object of course, is then sent the message with the selector ifTrue:ifFalse: and the arguments [a] and [b], which are two blocks. What happens is up to that object. Typically that object is either true (the sole instance of the class True) whose ifTrue:ifFalse: method evaluates the first argument, or false (the sole instance of the class False) whose ifTrue:ifFalse: method evaluates the second argument. Very neat and conceptually clean. It allows you to define your own control flow methods.

Ruby on the other hand compiles if statements and their kind as tests and branches, much as a C compiler would. We trade off a little flexibility for performance.

But, in my experience, that flexibility rarely got used in Smalltalk. Not only that but, in my day at least, the Smalltalk compilers would also compile ifTrue:ifFalse: to a test of the result of the ‘receiver’ and a branch. In fact I just tried defining a FakeBoolean class with an ifTrue: method and when I try to use it I see this:

must_be_boolean

That NonBooleanReceiver exception is like seeing the Wizard of Oz behind the curtain, this notion of no control flow, just messages is actually a bit of an illusion.

Again, while Ruby doesn’t even pretend to implement all control flow by messaging, it provides most of what the underlying Smalltalk mechanisms are really used for in the form of blocks used to implement iterators.

There are other aspects of Smalltalk which are both blessings and curses. The fact that Smalltalk has a persistent run-time image, containing all the development tools, which can be saved along with its state of execution, and restarted is quite powerful, alien to many programmers, and can drastically change your approach to deployment. Back when I was doing Smalltalk we always struggled with issues like the footprint of the image, how to strip out the development tools before deployment, and start-up time. Some of these problems might seem to be less severe with today’s hardware, but they are still issues.

I feel that I might be coming across a little too harshly on my old friend Smalltalk. It still provides a great programming environment, and serves as a source of inspiration which shouldn’t be overlooked, and I hope to see some of the powerful development tool features from Smalltalk appear with help from support in some of the emerging Ruby implementations. I’m glad to see that it seems to be making somewhat of a resurgence, along with dynamic languages in general. But for me right now, while I wouldn’t be unhappy if I had to go back to Smalltalk, but I feel happier with Ruby.

Posted in , ,  | Tags ,  | 5 comments | no trackbacks

On Ceremony and Training Wheels

Posted by Rick DeNatale Sun, 18 May 2008 14:15:00 GMT

The perennial topic of getting duck-typing in ruby has come up again. A ruby nuby wonders about the dangers of passing a “giraffe” object to a method expecting an “order.” Or asking an object to “draw”, expecting it to be a “brush” when it was really a “cowboy.”

These are reasonable questions, coming from someone who is used to a high-ceremony language which gives at least the illusion of protection from such “errors.” Note that method signatures in languages like Java can’t really protect from a draw method doing different things in different classes.

J. Cooper offered the following good advice:

Instead, look at it like this: how likely is a Giraffe able to do what an Order does? If the Giraffe doesn’t quack like an Order, than an exception is going to be thrown automatically anyway.

Just program in it, and see how often it ever actually bites you. Start with small things, work your way up.

The advice here is to tackle the problem of learning a language like Ruby with a certain amount of fearlessness. This reminds me of learning to ride a bike.

The traditional way of learning to ride a bicycle is to use training wheels, sometimes even progressively. Your dad might have installed the training wheels so that they touched the ground, turning the bike into a kind of tricycle with an extra, overly large back wheel between the normal ones. You think you’re riding a bike, but you’re really still on a trike.

The next stage, is for dad to raise the training wheels a bit so that you need to start learning to balance properly, but you can’t really tip too far. Now you’re riding something that kind of acts like a bicycle, but which “flops over” into tricycle mode.

If you never get past this stage, you never really learn to ride a bike. In an analogy with programming in Ruby, training wheels are chicken typing devices.

The truth is that bicycles and motorcycles operate quite differently than wheeled vehicles which keep three or more wheels on the ground, for one thing you steer by leaning, not with the handlebars or steering wheel. Learning to fly an airplane gives even stronger examples of having to learn that your instincts are wrong, and that you have to train yourself to “instinctively” know not only that you turn by banking rather than with the rudder, but that you control altitude primarily with the throttle, not the elevators, speed primarily with the elevators not the throttle, and so forth.

Now the use of training wheels, or flight simulators, might be considered a ceremony, although a necessary rite of passage for many learners. Given the high cost of mistakes in learning, it’s no doubt a good thing that student pilots get time in simulators and in dual control planes accompanied by a flight instructor before soloing. Although the way most young birds learn to fly is to be throw out of the nest to “sink” or “swim” so to speak.

In learning to program, it’s hard to see a difference between a simulator and reality, so it’s perfectly feasible to “fly the plane” from the start. The consequences of a mistake are no more dire than making a mistake in a flight simulator. It’s really just a matter of conquering fear, not to rely on chicken-typing, and the more mistakes you make and correct, the more quickly you come to grips with the differences in really using a dynamically typed language from earlier experiences.

Some can do this easier than others. For example, Alex, my 6-year old next-door neighbor recently jumped off his tricycle, and onto a bicycle (sans training wheels) and is now zooming around our cul-de-sac faster than ever before.

So if you’re struggling with how to program Ruby or a similar language because lacking ceremonial training wheels to “bridge the gap” from Java or a similar language. Might I suggest that you just jump in like Alex and give it a whirl.

Of course, it’s rarely easy to be as fearless as a 6-year old!

Posted in  | Tags , ,  | no comments | 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

Best Practice Patterns, Accessors and Encapsulation

Posted by Rick DeNatale Fri, 15 Feb 2008 13:29:00 GMT

Kent's Autograph to me on STBPP One of the classics in the Smalltalk literature, which has also had a big influence on the Ruby community is Kent Beck’s “Smalltalk Best Practice Patterns”, which captures the best practices for designing and coding Smalltalk programs. Back when it was published, I used to see Kent a few times a year, and happened to be in the Bay area when he made an author appearance at the Computer Literacy Bookstore in San Jose, where I got my copy, and the autograph shown here.

The Ruby language has many similarities with Smalltalk, so much of Kent’s advice applies to Ruby. I frequently hear prominent Rubyists mention the book.

On the other hand, Ruby is not exactly Smalltalk, so Kent’s book isn’t an exact fit to Ruby. I’ve been wanting to start writing about adapting some of these patterns to Ruby for a while, so this article will hopefully be the first in a series.

The Motivation For This Article

Recently on the ruby-talk forum a thread discussing accessor methods vs. direct instance variable access came up. This was a hot debate topic in the Smalltalk community back in the 90s, and Kent addressed it in two competing patterns in the book, one of which Ryan Davis (a.k.a ZenSpider) brought up in the conversation.

Read more...

Posted in , ,  | Tags , ,  | no comments | no trackbacks

Yegge's At It Again!

Posted by Rick DeNatale Tue, 12 Feb 2008 14:42:00 GMT

Another thought provoking piece from Steve Yegge.
Well, we also know that static types are just metadata. They’re a specialized kind of comment targeted at two kinds of readers: programmers and compilers. Static types tell a story about the computation, presumably to help both reader groups understand the intent of the program. But the static types can be thrown away at runtime, because in the end they’re just stylized comments. They’re like pedigree paperwork: it might make a certain insecure personality type happier about their dog, but the dog certainly doesn’t care. – Steve Yegge

And he’s getting the predictable responses from the static-typing advocates.

One quibble I’ve got with what I’ve just quoted, is that, in many languages, static types aren’t just comments. In the C++ implementations I’ve looked at, for example, the typing is used to generate runtime code which relies on the typing done at compile time. The other day I wrote about instance variable access in Java, Smalltalk and Ruby. In C++ instance variable (field) access is static and based on offsets. If a type error get’s past the compiler, say by a bad pointer manipulation, the run-time code can access a non-existant variable, possibly clobbering something vital.

In fact this “bug” is possible not in spite of static type checking, but because the compiler uses static type checking to affect the code, and “throws away” the information needed at run-time to avoid it.

Posted in  | Tags ,  | no comments | no trackbacks

Older posts: 1 2 3 ... 7