December 2005 Archives

Steve Mallett

AddThis Social Bookmark Button

What has been your experience with non-iTunes online music stores?

I’ve had inquiries from several folks about adding other music stores to iTunesLove, but I looked at several & none of them worked as elegantly for me as iTunes. Mind you, I’m biased so what say you?

AddThis Social Bookmark Button

I really like Austin’s earlier blog about Symbols and how they are just names.

I think the real confusion around symbols is three fold:

  1. The colon in the name
  2. The name Symbol
  3. How they relate to Strings
Gregory Brown

AddThis Social Bookmark Button

This will not come as a surprise to the experienced Rubyist, but for those in the crowd who are just learning, here is a bit of neat trivia for you to ponder.

Well, we all know that Fixnums (i.e. 1,2,3..) are objects in Ruby, right?
If you didn’t, now you do!

So it’s easy to do little tricks like

class Fixnum
   def +(other)
     self - ( -1 * other ) - 2
   end
end

which will break your math and let you impress people who are new to open class systems.
(i.e. 4 + 9 == 11 with the above definition)

You could also do functional hacks like

class Fixnum
  def squared
    self ** 2
  end
end

and get yourself 2.squared == 4

But one thing that I didn’t think about until Gary Wright mentioned it on RubyTalk is how Fixnums can have instance variables!

class Fixnum
  attr_accessor :letter
end

('a'..'z').each_with_index { |letter, index| index.letter = letter }

now 0.letter == 'a', 1.letter == 'b', etc etc

Is this useful? I’m not really sure, to be quite honest. But it sure is neat!
See the discussion in it’s original context at: http://www.ruby-forum.com/topic/50170

If you get any killer ideas for how to use such a feature, drop a comment here or there.

AddThis Social Bookmark Button

I wrote a couple of entries in this fancy new O’Reilly Ruby blog, and placed them in the “Opinion” category, which I evidently completely misunderstood to mean that it was for posting opinions.

Silly me. After this little follow-up, I’ll endeavor never post an actual opinion to a public forum again.

It turns out that the little “Opinion” label is far more widely construed to mean either “Universally True Factual Statements” or “Lies”, either of which appears to be grounds for getting Really Mad. It seems MovableType ought to have a little dropdown list for labeling your comments, providing convenient label options such as “Revenge”, “Retaliation”, “Retribution”, “Flame Strike”, and “Long List of Corrections”. Ideally it would allow you to select multiple comment categories.

Note: I will receive angry comments for that previous sentence, and also for this one, and for everything else I write for the rest of my life that makes it online, advertently or not. So will you, if you ever make the profound mistake of choosing that “Opinion” category in a blog post. You’ll also be quoted out of context all over the web, because apparently by choosing “Opinion”, you are also claiming that you are a Leading Expert at whatever random thing you’re talking about.

I’ve been a huge fan of Dave Barry’s writing for almost 20 years, but as of last week I have newfound respect for the man. He often points out that Alert Readers regularly send him angry factual corrections and even hate mail about his humor columns. How did he put up with it for his whole career? I’ll never know.

I’ve learned a few things in the past week. They are Universally True Facts! Ignore them at your own risk!

One is that if you ever opinionatedly claim that a specific group of people tends to be pedantic, something interesting happens: a whole bunch of people will pedantically inform you that you are incorrect. But they’re not just from the group you mentioned; they’re from everywhere. Pedants will materialize from every dimension to correct you. The corrections vary, of course. Some folks will just be negating what you said, occasionally colorfully. Some will announce that the *other* group (there’s always another group; people love taking sides) is even *more* pedantic. A few will announce that I’ve slightly misused the term “pedantic”, thus invalidating my entire article.

I’ll vouch one of my last-ever opinions: namely, that “correcting” someone’s opinion is automatically pedantic. Corrections inevitably overlook the basic problem that all communication is intrinsically ambiguous. Also, the shorter a statement is, the less universally true it becomes. So if you narrow in on any statement that someone makes, ignoring the surrounding context and failing to give some benefit of the doubt, you’ll always be able to find things to correct. But chances are good that you’ll also have missed their point.

Anyway, I’ve since realized that my opinionated claim wasn’t broad enough. Almost any arbitrary grouping of people connected to the web will have a tendency to appear pedantic, because the most pedantic people are very eager to post corrections (by definition), giving them a more vocal presence than their less pedantic and more forgiving peers. Plus, almost everyone is pedantic once in a while, depending on their mood that day.

By dropping just one word from the first of my two most infamous claims, I arrive at the slightly less incorrect opinion: “Pedantry: it’s just how things work in the world.” In the written, online world, anyway. Useful to know!

In an effort to partly forestall a flood of amusing corrections from pedants on the sharp lookout (a.k.a. “skimming”) for errors here that they can denounce, I’ll make the following statements of True Fact:

- I am a poorly-educated yokel, and I’m not an expert at anything.
- I speak only for myself.
- My opinions change daily, and I articulate them poorly.
- Everything I write is a baldfaced lie, except for the stuff you agree with.
- You’re right.

Feel free to quote me directly on any of those statements, by the way.

The other big thing I learned, related to my second infamous claim, is that people evidently *really* detest tax collectors, more so than I’d ever have guessed. Politicians, take note.

OK then! No more opinions from me, ever again. And I hereby revoke all previous opinions that I’ve ever stated or held at any time, however briefly. And as a nice catch-all algorithm, let’s agree that if I ever again accidentally voice something resembling an opinion or a possible factual error, whether you agree with it or not, then we’ll just assume I’m wrong and you’re right.

I suppose I should say something about Ruby, in keeping with the theme of this blog:

I like Ruby, but I miss list comprehensions from Python.1

However, some quick searches seem to indicate that someone somewhere has implemented them for Ruby, somehow. I guess I’ll go take a look!

<forever>
</opinion>
</forever>


[1] attention, pedants: I also miss them from Haskell.

Steve Mallett

AddThis Social Bookmark Button

Related link: http://ituneslove.com

Bored over the holidays, and somewhat disappointed at user generated suggestions within iTunes I spent the day building digg for iTunes: iTunesLove.com

I just finished, but it looks to be in working condition… submit some of your newly found gems and favorites! Three of my newly found favorites are in the submission queue waiting for you to discover.

Diggable!

Gregory Brown

AddThis Social Bookmark Button

I will try not to turn this entry into a rant, because we’ve seen plenty of that as of late.

However, I would like to share my experience regarding Ruby and the communities I’ve encountered in order to represent a sort of difference between the enthusiast and the hyper-enthusiast.

I will not make comparisons to other languages, because frankly, they aren’t relevant. I will however mention that I first played with Python 6 years ago and after about a year of tinkering went straight to Perl and stayed there until a little less than two years ago.

Upon finding Ruby, I was amazed by the language, but even more so by the community. A year and half ago or so when I started playing with it, I had never heard of DHH or 37 Signals or Rails or anything like that. I was enticed by my friend James Edward Gray II to learn the language, and soon thereafter began lurking about RubyTalk.

Soon I saw some names coming up a lot, both in conversations and in posts by the individuals themselves, such as David A. Black, Hal Fulton, Curt Hibbs, Chad Fowler, Jim Weirich, James Britt, and of course _why. This is just a random list of people who I noticed quite rapidly, but basically, these were people who came to Ruby before the Rails explosion, and they all have made significant contributions to the Ruby community.

There are hundreds of people I’ve spoken to in this community who have made some wonderful contributions to Ruby. Many of them are regulars on RubyTalk, some I’ve met at Ruby Users Groups (Such as new_haven.rb or NYC.rb), some I met at the RubyConf this past fall. These folks are what forms the core of the Ruby community.

In the last 3 to 6 months, there has been an incredible amount of buzz regarding Rails. It seems now, that the number of people who are interested in Rails moreso than Ruby, or those who are interested in Ruby because of Rails outnumbers the smaller core of those who just love Ruby. That doesn’t bother me one bit.

Part of growth is accepting the changing face of a community. As our userbase changes, the needs, interests, opinions and desires are sure to change as well. The only issue is that of identity, of reputation. I do not want to be lumped in with the hyper-enthusiast, if the meaning of the word is faith based decisions.

I also don’t want everyone who knows I’m into ruby to assume I’ve mastered Rails and that I love it as much as they do. I haven’t and I don’t. Rails is very nice, and I’m at the beginning of a rather large scale project in it, but to me, it’s just another impressive piece of Ruby software. No amount of marketing or hyper-enthusiasm is going to change my opinion on this. Maybe when I’m done with my project, I’ll have some substantial experience based opinion on it, but as for now, I’ll leave the defining word on Rails to those who know it and use it best.

The core issue here is that the level of noise is rising and rising in the communities. Or at least, some of us percieve it as noise. Do we really need to sell ruby? Do we really need to focus on standardization and point for point comparisions between language Foo and Bar? In my experience, Ruby sells itself. If you want to impress a potential employer, show them some software written in it, show them some things you’ve done. Prototype something quickly and cleanly and let them see it up front.

All this time that some very vocal members of the community spend ‘defending’ ruby or preaching it’s wonders from the mountaintops, myself and many others spend doing ruby. To me, that’s worth a lot more. To others, maybe it’s not. I have no problem with this difference in opinion. I just need to make it clear that I came to Ruby before it was cool, and even if people were calling me a tax collector, or even comparing me to a COBOL programmer, I’d still love it.

If you want to support Ruby, let it speak for itself in beautiful code. That is far louder (and far more useful) than faith based words. So this might have turned into a bit of a rant after all, but I just needed to speak up a bit for the Old School Rubyist, who doesn’t give a damn about what loud people on either side of the fence are saying.

AddThis Social Bookmark Button

Lots of people have been discussing symbols in Ruby, and seem have converged on the explanation that symbols should be used whenever you’re referring to a name (i.e. an identifier or keyword, essentially), even if you’re talking about a hypothetical name that doesn’t really exist in actual code yet.

I think this is the correct idiomatic usage, and it’s a pretty good way to explain symbols. But I also think it’s going to feel a bit hollow or contrived to someone coming to Ruby from a background in (say) JavaScript, Python, or even Java. If I were them, I’d be thinking: “Um, OK. Intent, intent, intent. Got it. But… isn’t a program-source identifier a fairly abstract notion to reify as a first-class object type, especially going so far as to give it a special syntax? And did I just use the word ‘reify’? Geez.”

I mean, Ruby symbols are right up there with numbers, strings, regexps and the like as first-class lexical entities. I’m guessing that this feels like a really odd decision to a lot of programmers. They might be comfortable with the “intent” explanation (which, incidentally, is similar to why I tell people I like tuples in Python so much — they help me express tuple-ish intent better than a list). Comfortable, sure, but they’re probably not wholly satisfied. It still smells a little fishy.

Am I right?

I’d like to offer my own humble take on Ruby symbols, in the hope that it’ll clear things up a teeny bit more. Nothing I’m going to say in any way negates what folks have concluded already, which is that symbols are best viewed as representing names in program code, not as “lightweight strings”.

Metaprogramming crash-course

Symbols as first-class objects are an idea that’s usually associated with Lisp. I don’t want to force you to learn any Lisp, and I won’t show you any Lisp today. But hopefully I can give you the flavor of how symbols are used in Lisp by describing a “hole” in Ruby that I hope will be fixed someday.

As a toy example, let’s take a look at the following Ruby code, which dynamically creates four methods and attaches them to an empty holder class, using eval.

#!/usr/bin/env ruby
# define a blank class as a holder for some methods
class BigMeanGiant
end

# Now add some silly-ish methods, using a flavor of eval.
# They're going to be instance methods, because it's as if
# we defined them inline inside the class definition above.
# When invoked, the giant yells the name of the method.

%w(fee fi fo fum).each do |name|
  BigMeanGiant.class_eval <<-EOS
    def #{name}() 
      puts 'Giant says:  #{name.upcase}!'
    end
  EOS
end

# invoke the methods, just for fun
begin
  g = BigMeanGiant.new
  g.fee
  g.fi
  g.fo
  g.fum
end

When you run this little program, it obligingly prints:

Giant says:  FEE!
Giant says:  FI!
Giant says:  FO!
Giant says:  FUM!

This program is roughly the “hello, world” of metaprogramming in Ruby. We’ve written some code that generates code on the fly: in our case, four nearly identical methods on BigMeanGiant called ‘fee’, ‘fi’, ‘fo’, and ‘fum’. It’s almost the same as if we’d written the code like this instead:

#!/usr/bin/env ruby

class BigMeanGiant
  def fee() puts "Giant says FEE!" end
  def fi()  puts "Giant says FI!"  end
  def fo()  puts "Giant says FO!"  end
  def fum() puts "Giant says FUM!" end
end

# invoke the methods, just for fun
begin
  g = BigMeanGiant.new
  g.fee
  g.fi
  g.fo
  g.fum
end

Running this version of the program has the same output.

What did we do that for?

Although this isn’t meant to be a lesson in metaprogramming, let’s make sure we’re all on the same page here. The second version is clearer, right? Why would you ever do the first version?

You almost certainly wouldn’t do it in an example this small, but the DRY principle tells us to avoid duplicating code. You can only get so far with function abstraction. Without metaprogramming, you can’t really compress the BigMeanGiant class much. You might factor out some of the repetition with a helper function:

class BigMeanGiant
  def say(msg) puts "Giant says #{msg}!" end
  def fee() say "FEE" end
  def fi()  say "FI" end
  def fo()  say "FO" end
  def fum() say "FUM" end
end

But it’s not much of a savings, because you still have to write all the stubs. Imagine you’re writing an HTMLOutputter class, with one method for every HTML tag — you’ll have to write a few dozen stubs, which is more than just annoying. It’s also probably more error-prone, since you’ll have so much code it’ll be harder to spot missed tags, duplicated tags, incorrect method bodies, and so on. And if you have to go back and change them all in some minor way, your refactoring editor may or may not be able to help, depending on what change you have in mind.

In short, having lots of similar-looking code is a Bad Thing.

To solve problems like this in Java, you either have to build elaborate and inevitably awkward dispatching infrastructure, or you have to use external code generators, then hack your build system to know how to generate and then use the generated code.

This, incidentally, is why you so often see generated code in large Java projects — it’s because Java offers no language-level ways to deal with problems like this. And of course, this is only one type of problem that’s solved elegantly with metaprogramming; there are many other classes of problem that are equally difficult to implement cleanly in Java.

OK, we’re all on the same page now, right? Generating code on the fly can lead to cleaner, more maintainable code, assuming you use taste and good judgement and blah blah blah. You get the idea.

The example explained

Continuing with my quest to get us all on the same page, let me make sure you understand the code in the first example. The relevant part is this blob right here:

%w(fee fi fo fum).each do |name|
  BigMeanGiant.class_eval <<-EOS
    def #{name}() 
      puts 'Giant says:  #{name.upcase}!'
    end
  EOS
end

This weird-looking snippet, interpreted in English, is saying:

  1. Make me a list of the strings “fee”, “fi”, “fo”, and “fum”.
  2. For each one of those strings:
    • substitute it into another string below, containing a Ruby method definition
      • The first time, use it as the method name.
      • The second time, use it (uppercased) as what the Giant says.
    • Then call class_eval to turn it into a real method on the BigMeanGiant class.

Make sense? We’re constructing method definitions in a loop, as strings, then passing them to the Ruby interpreter to attach them to a class. It’s not all that different from putting the code in a Ruby source file, then invoking the interpreter; it’s just that we’re controlling the process ourselves at runtime.

The argument to class_eval is a string. The string contains code. Before class_eval gets hold of it, it’s Pinocchio, wanting to be a Real Boy. class_eval is the fairy that sends him off to Pleasure Island to be ridiculed and learn valuable lessons, or whatever the interpreter does in its Big Black Box.

So far, so good. eval seems like a useful thing to have in your language, if you use it with caution.

Trouble in Paradise

So let’s say there’s a bug in my generated methods. Maybe the giant isn’t saying anything, or he’s saying the wrong thing. Let’s say I’m having trouble figuring out the bug by staring at my code-string, which is really just a template. It’s not real code until the interpreter finishes evaluating it and attaching it to the BigMeanGiant class.

So I fire up the debugger, and step through the code, and immediately notice a few things:

  1. The call to class_eval is atomic. The debugger just steps right over it.
  2. Calls to the generated methods are also atomic.
  3. I have no way of printing out the generated code.

In other words, your metaprogramming-generated code isn’t “first class” in the same way your normal source code is. It’s not visible to the debugger, and it’s not available to other tools either. (For instance, rdoc lets you include the source code in the generated documentation, but I don’t think there’s any easy way to have it know about your eval-generated code.)

There are some games you can play that might make some of these things achievable. For instance, you might be able to override class_eval to store the original source code (after the template substitution) in the class somewhere, and then provide an API for getting at it for your favorite debugger. But to the best of my knowledge, it’s not something that’s supported “out of the box” in Ruby, and it means that working with generated code is harder than it really needs to be.

Even if I’m completely mistaken here, and someone comments with a way to print out a generated method’s source code (which would be pretty nifty), the whole experience still falls remarkably short of the metaprogramming facilities in Lisp.

To clarify, let’s peer more closely into the lifecycle of that generated code. There are some distinct activities that rush right by us in Ruby, things we might actually want some control over.

We really will make our way to symbols soon, promise.

Constructing the code string

We start with a string, which the first example has in a “here doc” — one of Ruby’s genuine Perl-isms that you’re free to view with suspicion. Python’s syntax would be a triple-quoted string, which I think is nicer, but what’s done is done. Here’s the string again:

    def #{name}() 
      puts 'Giant says:  #{name.upcase}!'
    end

It could just as easily have been a normal, double-quoted string, even a one-liner:

  "def #{name}() puts 'Giant says: #{name.upcase}!' end"

However, because dynamically-generated code is notoriously tricky to debug, most of the time you’ll want to format code in template strings as clearly as possible.

I’m calling it a template because Ruby strings can contain inline expressions, delimited with #{}. In Java you’d use string concatenation, e.g.:

"Giant says: " + getThingGiantSays() + "!"

Python has the printf-like % operator, and other languages have their own approaches. The Ruby way is probably more readable if the substituted expressions are short; using something like sprintf (which Ruby also has) will be better if there are long expressions. Basically you want to do whatever makes the code template look as much as possible like the code it’s going to turn into.

Here’s Secret Observation #1: in Lisp, your code template isn’t a string. It’s a data structure that represents the tokenized and partially-parsed code. If Ruby had this feature, the BigMeanGiant example might look something like this:

%w(fee fi fo fum).each do |name|
  BigMeanGiant.class_eval START_CODE_TEMPLATE
    def #{name}() 
      puts 'Giant says:  #{name.upcase}!'
    end
  END_CODE_TEMPLATE
end

I put those big START/END tokens there in an attempt to make it clear that what’s inside them is NOT a real boy; it’s Pinocchio, and it will take some major Good Fairy work to make it real code.

But notice that the code inside the template is actually syntax-highlighted properly. When it was all inside a string (heredoc, double-quoted, or otherwise — it’s still just a string), it was all highlighted in light blue, which is what my editor tells me Strings should look like. My editor was nice enough to highlight the substitution expressions in brown, but you still need to realize they’re substituted before the final string is used as an argument to class_eval. But inside the CODE_TEMPLATE, we know it’s going to be code, so we can invoke the syntax-highlighter on it. Helps you see what’s going on more clearly. And auto-indenting, tagging, and other IDE functions will work on it. Muuuuuch nicer than code in a string, wouldn’t you agree?

Imagine that you could pass around one of those CODE_TEMPLATE doohickeys as an object, one that actually represented the Pinocchio-code in a way that let you traverse it and modify it before passing it off to eval. That seems like it could come in quite handy, and in fact it does. For one thing, it makes it far easier to do meta-metaprogramming, where you’re writing code that generates those code templates. But at a perhaps more mundane level, it makes it possible to create new syntactic constructs in the Ruby language.

At this point, some people will cringe and shudder and proclaim: “Evil! What you just said is Pure Evil!” Lots of programmers, maybe even most of them, are so irrationally afraid of new syntax that they’d rather leaf through hundreds of pages of similar-looking object-oriented calls than accept one new syntactic construct. I blogged about this once, in an article called Language Trickery and EJB. That article actually managed to convince a bunch of hardcore Java programmers that new syntax might actually be a useful tool. Maybe it’ll convince you too. If not, well, feel free to skip to the next section.

It would actually take me too far afield to go through a detailed example of how adding a new syntactic control-flow construct to Ruby could turn into a huge benefit for your project. Imagine, though, that Ruby didn’t have here-docs, and that you were practically drooling with jealousy over Python’s triple-quoted strings. If you’re a Java programmer, and you’re not drooling purely out of habit, then you should definitely drool over multi-line strings. It boggles the mind that they didn’t include it as a language feature, and in Java we wind up doing zillions of manual concatenations to produce long strings (which usually by then look nothing like the thing they’re trying to represent.) Ah, me.

If Ruby didn’t have here-docs, but Ruby had those CODE_TEMPLATE thingies and one system hook that allowed you to control the evaluation of those templates, then you could implement here-docs pretty easily. Because the code-to-be is represented as a data structure, allowing you to quickly and easily filter out the #{}-substitution elements, you could simply evaluate whatever’s inside those elements, and not evaluate anything else in the template. That’s all they really do. And of course (much) more sophisticated syntactic constructs are also possible, if you put in more work.

That’s the kind of thing Lisp programmers do for breakfast before going and writing their application code. And the funny thing is, it could really be super easy in Ruby — maybe even easier than in Lisp. It’s just that Ruby doesn’t support it today.

If the hairs are all standing up on the back of your neck, and you’re just recovering from shock and trying to think of the dirtiest word you could possibly call me, well, take a few deep breaths, nice and slow. It just means I’m a dog person and you’re a cat person, or something like that. Let’s not bite each other. Many people (notably Paul Graham in “On Lisp”) have spent lots of effort explaining how this kind of programming has to be treated with MUCH more deference and caution than ordinary API programming. Language extensions and minilanguages can be extremely powerful and useful — imagine where we’d be without regular expressions, for instance — but they also require tons more care, documentation, and thought than defining an ordinary function.

You’re already sort of doing this kind of “language extension” programming every time you call eval — for that matter, you’re doing it whenever you invoke a separate code generator, or open up a class and add stuff to it, or use a tool like yacc or ANTLR. We’re completely surrounded by languages, large and small, all the way down to the minilanguage you use for ordering coffee at Starbucks. It’d be hard to get along without them.

Evaluation

Once you have that code template as an actual object, as opposed to a string that you need to parse yourself, then you could do all sorts of things with it. For one thing, you could pretty-print it. It’s effectively in parse-tree format, so all you’d need to do is decide the rules for line breaks and spacing between various token types. For another thing, you could tell your debugger about it, which would allow you to inspect and step through generated code. And evaluation — the creation of actual code from your template — would no longer be the black box that it is in Ruby today (and in Python, Perl and JavaScript, for that matter.) More control means more opportunities to remove DRY violations, and do so in a way that has strong(er) long-term maintainability characteristics. I mean, you have to admit, not being able to inspect or step through your generated code makes maintenance a bit of a tricky proposition.

(Note: see the important correction Jim Weirich made in the comments section. –steve)

Symbols at last

Those nonexistent code templates I’ve been referring to — that is, objects (collections, really) that represent snippets of code to be evaluated — they’re really just syntax trees representing your source code. They’re similar to the output you’d get from any parser, including generated parsers from tools like ANTLR. Or maybe a more familiar example is the XML DOM — an object-tree representation of the parsed XML file. You have to admit, working with a DOM is a lot more convenient than working with a string containing raw XML. It’s a huge difference, and it’s a feature Lisp has that Ruby mostly lacks, at least today. A set of features, really: it’s a rich programming domain.

In a system with first-class syntax trees represented as language entities, in a way that allows you to interact with the lexer, parser, and evaluator (i.e. different components of the Ruby interpreter), symbols make a whole lot more sense. A symbol is literally an object that represents a name in the code tree. If you had a code template snippet representing this code:

  def fum() say "FUM" end

Then your syntax tree would contain a Symbol object for each token in the code except for the string “FUM” (which would be a String), because that’s just a string and not a source identifier or keyword, and also except for the parens in the arg list, but that’s another long story that we don’t have time for today.

So Ruby’s symbols are really a placeholder for grand things to come. Ruby is already a very powerful, capable language, but it has some weaknesses in its ability to process Ruby code at runtime. Your only real tool today is eval (which comes in several flavors in Ruby, but that’s irrelevant to our discussion), and it’s a big black box. Once your code template is handed over to the Good Fairy, crossing that magical line between your program and the Ruby interpreter, you’ve lost it, and what you get back is effectively an opaque binary blob wrapped in a thin Method (or UnboundMethod, etc.) class that doesn’t remember much about its original symbolic representation.

Well, that went on way too long. Was it helpful?

AddThis Social Bookmark Button

I recently started writing an article about Domain Specific Languages (DSL’s) and Ruby. While conceptually I think I understand what a DSL is, I think a specific definition is elusive. After scrutinizing several articles and the Wikipedia, I can propose a limited definition of a DSL as a custom language designed to solve a specific problem.

Some examples of DSL’s listed are unix mini (or little) languages, such as sed, awk, troff, m4 or make. The list is quite long, and actually, could go on forever, since most any language, computer based or not, could be considered a DSL. But for now, I’ll limit this entry to languages used in the computer domain.

From my work, I see DSLs used for two main purposes. One, is as a friendly way to provide data (configuration or otherwise) to a program. The other is a friendly way to let users write business rules for a particular task. This is usually motivated by the desire to let the end user write code without realizing they are actually coding.

Except for very simple command lists, you see this second type less often because the complexity usually requires one to either build a real mini language or, if using a traditional general purpose language (GPL), the derived DSL is usually more cryptic or complex than just using the GPL itself.

When designing a DSL, the programmer has to weigh the options of taking the effort to build a full featured language (using the likes of YACC or Bison) or to make a simpler language that can usually be parsed with a hand built parser. It’s the choice between ’simple and now’ or ‘full featured and later’.

But the danger is that ’simple and now’ languages, if successful, tend to grow into ugly and complex later.

Consider make. I’m not intimately familar with the origin of this language, but here is my wild guess as to how it came about:

Programmer: Hmm, I’m tired of repeating these build steps over and over. I need to make a control file to do this for me. I also want to be able to take this with me to other platforms, so I’ll need to use a portable language. Hmm, I know C, I’ll use it.

Now lets see, I don’t want to go to the effort of writing a real language, I just need some simple features, so I’ll write my own parser.

I need a simple way to defined dependencies and a target, something like:

  target : dependencies

Yeah, the ‘:’ is good. You don’t see colons used much in filenames.
Now I need to define a list of actions. Hmm, how about:

  target : dependencies
  begin_actions
    action1
    action2
    ...
  end_actions

Wow, this is hard. These blocks are killing me. Hey, wait a minute, I can get rid of these blocks if I just make the user use a tab as the first character on an action line, kind of like Fortran, but more sinister since you can’t see the tab character (woohaahaaha). This way I can do a simple character test in C and don’t have to do any complex parsing. The user shouldn’t mind too much.

Having a critical syntax that depends upon an invisible character is just a horrible design — for the end user. For the programmer, it was pragmatic and reasonable.

Instead of writing a homegrown parser, another alternative is to create a grammar and use a tool like YACC and create a parser. This definitely falls on the complex side of the scale. For someone who doesn’t do this everyday, even simple tasks take a huge amount of brain power and one ends up focusing more on minutia of the DSL, and not on higher level usability issues.

Several years ago I needed to write a description file of geometrical stack. Several vendors had their own format, which were mostly line based, but a couple supported scoping inside a block. None, however, supported variables or constants. Their files were basically glorified configuration files.

I started to write my own using Racc. It was a great learning experience for me. We chose to write our own parser because we wanted to limit what could be done in the file (why, I don’t know). I spent about three weeks on the project and things were progessing nicely. It almost looked like Ruby. But, it was tedious, and other things got prioritized over the project before I could finish.

Later I revisited the project. This time I thought, hey, why should I write my own parser, XML/XSLT and xmlproc will do this for me. So, within a couple of days, I had done what took me three weeks previously. I thought it looked readable and the time and was able to partially convince a colleage that it was readable. About a week later, when I came back and revisited the file, I realized, XML is not readable. Sure, if your brain is in XML mode, then it can filter out the syntax noise. But when one is concentrating on getting a particular job accomplished and thier brain is forced to task switch between their problem domain and mentally parsing XML, overloaded synapses are a certainty.

The third time around, after the Ruby DSL hype had been going around for a while, I decided to use Ruby. This time, I was able to create the DSL in about five minutes. It was readable, and I was able to focus on the end users frame of reference.

The moral of this story is, don’t write a mini language if you don’t have too. And, don’t settle for a simple DSL when a full featured one is needed. Consider extending a GPL into a DSL. Particularly an expressive language that is good at creating a readable DSL — like Ruby.

Back to the original question of a what exactly is a DSL. One can either write a DSL from scratch or use a GPL with a few added functions to create a DSL. But if any GPL can be made into a DSL, doesn’t that make all languages DSLs?

AddThis Social Bookmark Button

Both Jim Weirich and Yohanes Santoso posted about Ruby’s Symbol class today. As Yohanes noted, there’s not many weeks that go by where there’s no question about Symbols. I thought I’d throw in my two cents, expanding on a mailing list response ([ruby-talk:172842]). First, let’s look at what ri has to say about Symbol objects:

Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :"string" literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program’s execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.

The beginning of the confusion about Symbols being like Strings is straight from the source in this case. As both Yohanes and Jim point out, though, Symbols shouldn’t be used as “Strings-lite”. At a minimum, to be useful that way, you’d have to convert each Symbol into a String (#to_s) before you could operate on it. If you shouldn’t use Symbols as if they were immutable strings, what good are they? Yohanes covers the theory well: helping to express intent. Jim covers the practical reasons well:

  1. Naming keyword options in a method argument list.
  2. Naming enumerated values (e.g. like enums in C).
  3. Naming options in an option hash table.

As Jim says, “Symbols are about naming and identifying things.” I don’t quite agree with his definition (“A Symbol is an object with a name”), preferring to say that a Symbol is an object that is a name. It’s a very subtle difference, mind you, but an important one in that there is no meaningful distinction between a Symbol and the name that it represents. That said, we’re still left with the question asked by Steve Litt, “One thing—why not some_call(:@my_variable)?”

This is where Yohanes’s discussion on intent matters. You aren’t naming your variable when you call attr_accessor. You’re naming your method. The magic here isn’t in the Symbol; it’s in attr_accessor.

>> class Foo
>>   attr_accessor :bar
>> end
=> nil
>> baz = Foo.new
=> #<Foo:0x2d8aea8>

Thus far, baz has no instance variables. But it does have two instance methods:

>> baz.methods - Object.methods
=> ["bar", "bar="]

If I call the reader method (Foo#bar), I still don’t get an instance variable:

>> baz.bar
=> nil
>> baz
=> #<Foo:0x2d8aea8>

It’s only when I call the setter method (Foo#bar=) that my instance variable is created:

>> baz.bar = 32
=> 32
>> baz
=> #<Foo:0x2d8aea8 @bar=32>

The intent of the Symbol is that it’s just a name. The intent of attr_accessor is that it creates two methods for each name that it’s been given. It is almost coincidental that these methods work on a variable of the same name. It doesn’t have to be the same, as I demonstrate below.

require 'digest/md5'
class Module
  def md5_accessor(*names)
    names.each do |name|
      var = Digest::MD5.hexdigest(rand(65536).to_s)
      define_method(name) { || instance_variable_get("@_#{var}") }
      define_method("#{name}=") { |v| instance_variable_set("@_#{var}", v) }
    end
    nil
  end
end

class Foo
  md5_accessor :bar, :baz
end

moo = Foo.new
moo.bar = 5
moo.baz = 7
moo
puts moo.bar, moo.baz
Gregory Brown

AddThis Social Bookmark Button

I’ve always liked the fact that nil evaluates to false. This is handy in conditional expressions and makes ||= possible.

However, something I didn’t expect is a bit annoying:
nil.to_i gives you a 0, which evaluates to true in ruby.

So stuff like this happens:

irb(main):002:0> puts "hello" if nil.to_i
hello
=> nil

At a first glance, it seems like zero might have been better replaced by nil or an exception.

Does anyone have any insight as to why nil.to_i returns zero and why that might be more useful or better than an alternative solution?

James Britt

AddThis Social Bookmark Button

As has become tradition, Christmas brings us a new version of Ruby. Thanks to Santa Matz, Ruby 1.8.4 is now available.
ChangeLogs can be found here.
A big thanks to Matz and all those working hard to make each new release better than the last.

Steve Mallett

AddThis Social Bookmark Button

Two great newbie resources made my attention-width this morning:

1) Learn to Program (using Ruby), by Chris Pine. There are tons of books out there that assume you know how to program already and so the title and subject end up being Learn to Program XXXX, but what about Newbies? Chris steps in and decided to use Ruby as the base. His book is due soon as well, which he assures me is even funnier.

2) Rails Weenie. Hey, that’s me! “Sign up and you start off with five points. Offer up points for your questions. The harder the question, the more points you wager.”

AddThis Social Bookmark Button

No doubt Rails is becoming popular - just looking at the number of folks joining the ruby-talk mailing list and asking Rails specific questions. It’s happening very frequently now - I think mainly because of the confusion between what is Ruby and what is Ruby on Rails. For the most part, they are kindly directed over to the Rails mailing list for better help with their questions. However, the frequency of this question and reply session is picking up dramatically. Thus, it seems like the most natural solution is to rename either Ruby or Ruby on Rails to something that helps differentiate between the two.

I’m just kidding about renaming the projects. But the comment board is open - hit us up with some of your (humorous) thoughts.

pat eyler

AddThis Social Bookmark Button

Tonight, the Utah Ruby Users Group had its monthly meeting. We’ve been hovering aroung 20 attendees for several months now, with a traditional presentation format. This month seemed like a good time to do something different, so we decided to try a more hands-on meeting.

Jamis Buck (of Net::SSH, Needle, and Rails fame) put together several ‘topics’ that we could pair up and hack on. The idea was to let people pair up and work on things that were interesting and skill level appropriate, and at the end of the night compare notes on how pair programming and strict test first programming worked for people.

I don’t know if it was the meeting plan, or the proximity to the holidays, but things didn’t work out like we’d hoped. Only about 6 people showed up, and the hacking topics didn’t really appeal to us. One of the attendees had a question about getting AJAX working in a little Rails app he’d been working on though, so Jamis led an impromptu 90 minute session on using AJAX in Rails. (I guess that’s what being agile is all about.)

For January, we’re going back to our old format. I understand the presentation will be about Ruby/Cocoa. Whatever it is, I plan on being there. With this group, missing a meeting means you’re really missing out.

Are you involved in your local Ruby Brigade? If not, do you know what you’re missing?

James Britt

AddThis Social Bookmark Button

A few nights ago I had the good fortune of leading the first Phoenix Ruby Users Group meeting in many months, and the difference between this one and the previous meeting were amazing. Expecting to see maybe eight or ten people, a fairly sizable training room (graciously provided by Cyclone Commerce) was completely filled. By rough estimate there were 25 to 30 people. Were in the world did they come from?

A bit of history: I came to Ruby sometime in 2000 or 2001. It was probably Dave Thomas’ article in Dr. Dobbs that piqued my interest. I remember browsing through a copy of the first edition of Programming Ruby at a local Barnes & Noble, and being put off by some of the syntax, but, for reasons now unknown, I gave Ruby another shot. Part of learning Ruby was getting active in the Ruby community, which meant lurking, then participating, on the ruby-talk mailing list, and learning about the main Ruby Web sites, such as Ruby Central and Ruby Garden.

Some time early on, interested in meeting other Rubyists, I added my name to the Ruby Garden wiki page for the Phoenix Ruby Users Group. There were, I think, two names already there. I may have tried sending E-mail to these people, but nothing ever came about. It wasn’t until early 2005 that, hearing that people were doing well using (then free) Meetup.com to organize user groups that I did actually attend my first Phoenix meeting. On the up side, I met great people (in fact, it led to my joining them in the Web design and development company, 30 Second Rule ). However, over the course of three or four meetings, it was always the same three people, and the user group, as such, just dissolved. Though the Rails Summer of Hype meant Ruby was getting routine attention on various Web sites (such as Slashdot, and here on O’Reilly), it seemed as though Phoenix was just never going to be a hotbed of Ruby activity.

Getting Refreshed

However, a few months ago, a few folks from some local companies began to realize that indeed there were a number of interesting people and companies here in the Valley of the Sun , but for the most part they were operating in complete ignorance of one other. Copping a tune from Refresh Dallas, Refresh Phoenix was born, with the goal of bringing together Web developers and designers in a relaxed social environment so we could meet, get acquainted, learn new things, and share ideas and experiences.

The first meeting in November went great. Our fears of pitiful turnout were completely unfounded; there were probably 25 to 30 people there. It turned out that many people were thinking the same thing, and were eager to get out of their cubicles and actually talk with people, face-to-face.

The big surprise for me, though, came as we asked everyone gathered to say a bit about themselves, what they do, and what things were they interesting in. Probably half a dozen people mentioned Ruby or Ruby and Rails, saying either they were just getting started or looking learn.

At the second Refresh Phoenix meeting I announced that I was looking to revive the Phoenix Ruby group; before I left I collected a dozen names. Shortly afterward I made plans for our first meeting, expecting perhaps eight or ten of those on my list to show up, as well as a few folks from Cyclone Commerce. I was mistaken.

The meeting was scheduled to begin at 6:00 PM, and by 6:15 PM nearly every seat in the good-sized training room was taken. Wow.

Since this was largely a Get Acquainted and Figure Stuff Out meeting, I asked if each person could say who they were, how much Ruby they knew, and what they hoped to get from the group. The responses were somewhat surprising. Most people had taken a stab at Ruby coding, but were just getting started. That made some intuitive sense. I was really expecting to hear a room full of people telling me they all wanted to learn Rails. But, while that did get some mention, most people expressed a primary interest in learning Ruby itself, in expanding their general programming skill set. Some wanted to get away from Java, some wanted a better understanding of meta-programing with a dynamic language. But the interest was in Ruby itself, not some particular framework or application.

Since so many were new to Ruby, I offered up some resources. By a show of hands, though, most of the room seemed unfamiliar with the ruby-talk mailing list (home to the world’s friendliest developer community) and most of what I consider the better known Ruby Web sites. So here was a room full of people, many of whom were already somewhat familiar with Ruby, many of whom had taken steps to learn Ruby, yet were not even lurking on ruby-talk or surfing the Ruby Garden wiki. (Thankfully, at least some folks already knew about ruby-doc.org.)

The meeting went great, and I’m looking forward to the next one, in January. It’s really nice to be around so many people so interested in expanding their horizons.

The Takeaway

I think one tends to get the impression that the discussions on ruby-talk, or on Slashdot or O’Reilly, or on the many Ruby blogs, somehow represent the “Ruby community”, but the reality is that there are good numbers of people actively interested in Ruby, but unaware or indifferent to certain public forums and currents. This suggests that while activity on the main outlets correctly indicate a growing interesting in Ruby, the real numbers are much larger than may be readily apparent. And the comments from people I spoke with suggest that while certain topics and tool sets get a fair amount of public buzz, there is tremendous interest in all the myriad aspects of Ruby.

If you are a publisher, you may want to rethink jumping on whatever is the current bandwagon for your next Ruby book. People want to know all about all of Ruby. And if you are part of a company looking for developers, thinking that Ruby may give you an edge, but concerned about finding people, know this: There are far more Rubyists than you know.

AddThis Social Bookmark Button

In my previous entry I had some takers on trying to write a nice, compact, method that handled round a float down to a certain decimal place.

For fun, I decided to benchmark each implementation, along with a small C implementation I wrote. Here’s the lineup:

require 'benchmark'
require 'prec_c'
include Benchmark

class Float
  def prec_caleb1(x)
    sprintf("%.0" + x.to_i.to_s + "f", self).to_f
  end

  def prec_caleb2(x)
    (("%.0" + x.to_i.to_s + "f") % self).to_f
  end

  def prec_james(x)
    ("%.0#{x.to_i}f" % self).to_f
  end

  def prec_jonas(x)
    (self * 10**x).to_i / (10**x).to_f
  end

  def prec_fansipans(x)
    to_s[/.*..{#{x}}/]
  end
end

n = 50000
bm do |x|
  r = rand(6)
  x.report { for i in 1..n; 5.44235102.prec_c(r); end; }
  x.report { for i in 1..n; 5.44235102.prec_caleb1(r); end; }
  x.report { for i in 1..n; 5.44235102.prec_caleb2(r); end; }
  x.report { for i in 1..n; 5.44235102.prec_james(r); end; }
  x.report { for i in 1..n; 5.44235102.prec_jonas(r); end; }
  x.report { for i in 1..n; 5.44235102.prec_fansipans(r); end; }
end

I ran the code a couple of times to make sure the results came up rough the same. They did. Here are the results (sorry for the formatting):

impl user system total real
caleb_c 0.330000 0.000000 0.330000 ( 0.325121)

caleb1 0.450000 0.000000 0.450000 ( 0.454775)

caleb2 0.460000 0.000000 0.460000 ( 0.456334)

james 0.410000 0.000000 0.410000 ( 0.405698)

jonas 0.480000 0.000000 0.480000 ( 0.486741)

fansipans 0.950000 0.000000 0.950000 ( 0.944716)

It looks like James is the winner, at least in terms of efficiency (as long as you don’t count my C extension, which kind of breaks the Ruby spirit).

Here’s that code, in case you’re interested:

#include "ruby.h"
#include <signal.h>
#include <time.h>

static VALUE prec_c(VALUE klass, VALUE prec)
{
  VALUE str = rb_str_plus( rb_str_new2("%."), rb_funcall(prec, rb_intern("to_s"), 0) );
  VALUE str2 = rb_str_plus( str, rb_str_new2("f") );

  char s[20];

  sprintf(s, StringValuePtr(str2), NUM2DBL(klass) );
  return rb_funcall(rb_str_new2(s), rb_intern("to_f"), 0);
}

void Init_prec_c() {
  rb_define_method(rb_cFloat, "prec_c", prec_c, 1);
}

I’m sure someone can find some fallacies in my code that makes for unfairness in my benchmarking, but for the most part I think the data is fairly reliable.

Robby Russell

AddThis Social Bookmark Button

Related link: http://www.oreillynet.com/ruby

I got to post one of the first entries on the new O’Reilly Ruby blog. Steve Mallett organized this and it finally was launched the other day. In the past day there have been half a dozen entries by famous Rubyists. I look forward to see what people write.

Take a look at my 90 second tutorial on using Enumerable. It’s true, I just wanted to be one of the first people to post on the new blog. ;-)

As Ruby has quickly gained quite a bit of attention over the year, it makes me wonder what the Ruby world will look like after 2006. Any predictions?

Steve Mallett

AddThis Social Bookmark Button

Pop quiz, hot shot! What two topics are so high up the tech. meme ladder that they make geeks quiver at the mouth?

Right! Asterick & Rails. Now, put them together for mouth foaming madness in Hacking Asterisk and Rails with RAGI.

In this article, I’ll provide a quick overview of how Asterisk, the open source PBX, can be used as a general-purpose “telephony protocol server,” and can be connected to Ruby on Rails to create a rapid prototyping environment for creating next-generation VoIP applications and services.

Steve Mallett

AddThis Social Bookmark Button

Related link: http://www.oreillynet.com/ruby

I’m extremely pleased to announce that we’ve launched the O’Reilly Ruby group-weblog. It’s a Ruby holiday-treat!

Like Ruby we wanted to be pragmatic (nod to Dave) in our approach to covering an exciting and rapidly developing target. Hence; you will witness the new group blog of some 10-ought ruby-ists extraordinaire. Who better to keep you in the know of what is possibly the coolest, most fun to use - and did I mention powerful - programming languages yet than those whose helping hands are ruby red up to the elbows?

To my delight the blog has begun to fill in with Ruby goodness - “Hello, World!” through the ages, a 90 sec. tutorial on Enumerable, Ruby bot battles, and a good hearted disagreement with Elliot Harold.

Enjoy!

Robby Russell

AddThis Social Bookmark Button

Disclaimer: This is my first post on the O’Reilly Ruby blog. I decided that I wanted to do my own Hello World… but decided that I’d just pick on our friend Enumerable and give you a quick 90 second tutorial. Start your watch… now.

Let’s build an array of hashes

Let’s take for example this nice array that we then populate with some hashes. In this case, a few of my co-workers and their current job titles.

argonistas = Array.new
argonistas << { :full_name => 'Allison Beckwith', :title => 'Creative Director' }
argonistas << { :full_name => 'Jeremy Voorhis', :title => 'Lead Architect' }
argonistas << { :full_name => 'Robby Russell', :title => 'Founder' }
argonistas << { :full_name => 'David Gibbons', :title => 'Lead Systems Adminstrator' }

This should be pretty straight-forward.

How do we #sort_by full name?

Okay, let’s sort this array of hashes by the value of full_name in each hash. To do this, we can use #sort_by which comes with the Enumberable module.

argonistas.sort_by { |argonite| argonite[:full_name] }

Great. We have the ability to quickly sort the array of hashes.

Let’s throw that array into a block

Let’s take one step further and iterate through each hash in the array and output everyones full name and job title. What we can do is pass our array above to a block and print out these values.

argonistas.sort_by { |argonite| argonite[:full_name] }.each do |argonite|
  puts "#{argonite[:full_name]}, #{argonite[:title]}"
end

Your STDOUT loves your hash keys

With this, we now get the following output:

Allison Beckwith, Creative Director
David Gibbons, Lead Systems Adminstrator
Jeremy Voorhis, Lead Architect
Robby Russell, Founder

It’s Over!

As you can see, it doesn’t take much to really embrace the power of Ruby without turning your code into an ugly mess.

Gregory Brown

AddThis Social Bookmark Button

Though it’s safe to say you shouldn’t judge a book by it’s cover, the first 50 pages or so should give you a sufficient feel for what to expect in the rest of the book. At least that is the assumption I am making in this first look at Enterprise Integration with Ruby, a beta book currently being offered by The Pragmatic Programmers.

Just digging into the first few chapters, I’m already impressed. Immediately the reader is greeted with the standard quarky (if a bit dry) imaginary scenario to progress through the book with. The example in this case is PragBouqet, a flower shop. Though it would be wonderful to see a book that did not use some sort of E-Commerce as it’s example, this does provide a solid base for clear use cases and sample applications.

The book’s main feature as far as I can tell is the sizeable amount of code examples that fill it’s pages. The user is not given excruciating detail about what each and every line does, but is given a really wonderful description of the problem, and why it’s being solved the particular way it’s being solved.

The author takes an iterative approach, which is common in most Pragmatic titles. However, instead of being a little overwhelmed by wild refactoring at the large scale, Enterprise Integration seems to chisel off smaller chunks at a time. Though the book is intended for experienced developers, this approach is without a doubt favorable for lowering the learning curve.

The narrative approach and the copious amount of output make this book readable even without an irb prompt open. The examples are clear enough where you can get a qualitative feel for them without burning too many brain cells.

The only drawbacks of this approach is that it makes using the book as a reference a bit more complicated. Though the chapters are modular, the example spans across them and if you like to jump in midstream, this might complicate things a bit. Also, the examples are fairly specific to their domain, which means you’ll probably need to read through the example and a bit of the chapter before fully getting a feel for what is going on.

That having been said, one of the unexpected gems of this book is it’s wonderful chapter on ActiveRecord. Most other publications regarding ActiveRecord, whether online or in print, spend a ton of time talking about integrating it with Rails. Of course, this makes sense for that problem domain, but if you’re trying to get a wholistic feel for what ActiveRecord can do for you as an ORM rather than a support library to Rails. , good qualitative sources are hard to find. Of course, Agile Web Development with Rails provides a great reference for this, but if you were left scratching your head a bit… Enterprise Integration with Ruby might provide a good way to fill in the gap.

Of course, there are some of the annoying issues that are to be expected in beta books, such as code abruptly spanning pages and other minor formatting isssues, though these are minimal enough where they do not effect your experience enough for it to matter.

There is also a wonderful quotable phrase in the book:

Don’t like the sunflowers? Destroy ‘em!

Any book that tells me I can destroy wildlife if it doesn’t fit my fancy is a good book to me!

So that’s my impression after 50 pages, what’s yours?

Curt Hibbs

AddThis Social Bookmark Button

I thought that “Hello World” would be very appropriate for my first post to O’Reilly’s new Ruby blog.

What got me thinking about this was a very funny article I just read that showed how the form of a Hello World program changes as the developer progresses in his career. Here are a few excerpts:

High School/Jr.High

    10 PRINT "HELLO WORLD"
    20 END

First year in College

    program Hello(input, output)
      begin
	writeln('Hello World')
      end.

Senior year in College

    (defun hello
      (print
	(cons 'Hello (list 'World))))

New professional

    #include
    void main(void)
    {
      char *message[] = {"Hello ", "World"};
      int i;
      for(i = 0; i < 2; ++i)
	printf("%s", message[i]);
      printf("n");
    }

After this they get too long to post here, but its really hilarious. I especially liked the "Master Programmer" example which was an MS COM/C++ program (which brings back painful memories).

As these Hello World programs got progressively more complex, it made me think about how the Ruby version returns to utter simplicity:

    puts 'Hello World!'

Which is much better than the Java version (my previous language of choice):

    // Must be stored in a file called "hello.java"
    public class hello {
        static public void main(String[] argv) {
            System.out.println("Hello world!");
        }
    }

Even in Ruby, a Hello World program can be educational, judiciously showing off some of the language features. My favorite such Hello World program in Ruby is:

    # The Greeter class
    class Greeter
      def initialize(name)
        @name = name.capitalize
      end

      def salute
        puts "Hello #{@name}!"
      end
    end

    # Create a new object
    g = Greeter.new("world")

    # Output "Hello World!"
    g.salute

That nice little piece of Ruby code was written by either John Long, Ben Giddings, or Michel Martins — I can’t remember which one, so I mention all three.

Anyway, go read the Hello World Programs page and have a little chuckle!

AddThis Social Bookmark Button

Bruce Eckel really doesn’t like Ruby. I don’t know why he doesn’t; I know he’s explained it in the past. Yes, there’s a lot of enthusiasm around Ruby and Ruby on Rails lately: this group blog has certainly been created because of this enthusiasm. But the enthusiasts and the detractors both distract from the larger reality that there’s never going to be a single programming language that is best suited for all projects.

The problem is that some people—this includes some Rubyists—who think that Ruby is in a language war with Python (or Java or…) and that “there can be only one.” Unlike Highlander, this isn’t a zero-sum game. While the Rails crew can be extremely enthusiastic about Rails and Ruby, few of them pretend that Rails is a silver bullet for every problem. Rails is a targeted application framework that takes advantage of—and perhaps even extends—the opinionated and expressive nature of Ruby.

As I work on PDF::Writer, I freely admit that its origin came from the R&OS cPDF library written in gasp! PHP. I’ve taken it far beyond cPDF, and I have looked at Perl’s PDF::API2, Python’s ReportLab, Java’s iText (and the C# port iTextSharp), and will be looking at CL-PDF for Common Lisp (if anyone has other open source libraries that are worth studying, please let me know) as I formulate both the implementation and th