2004-07-29

Ruby scratches

I have a love/hate relationship with Ruby. It's not congenitally evil like Perl, but it does have some rather nasty disfigurements. Here's how it annoyed me today:

mercury:/tmp$ cat -n ruby-is-stupid.rb
1 #!/usr/bin/ruby -w
2 a = 4
3 if a == 1
4 puts("one")
5 else if a == 2
6 puts("two")
7 else
8 puts("many")
9 end
mercury:/tmp$ ./ruby-is-stupid.rb
./ruby-is-stupid.rb:9: parse error

The error is actually on line 5, where I have else if instead of the Perlism elsif. But hey, if "parse error at end of input" is good enough for gcc, why shouldn't it be good enough for Ruby?

This is a lot harder to spot in a real program.

An ugly design choice (elsif) combined with a poor implementation (parse error). Distractions like this really make my day.

Ruby's puts has a nasty wart, too. It doesn't do what you might think given its partnership with print, and the existence of seemingly similar choices in other languages. Java's print and println, say. Or C's printf and puts.

What Ruby's puts does depends on the string it's given. It doesn't output the string it's given followed by '\n'. It outputs the string it's given and, if that string didn't already end with '\n', it'll append a '\n'. Which is a great way to have a program that works only on most input.

The idea is that you can be sloppy about whether your string ends in a newline or not. And that puts means "print this, ensuring there's exactly one newline on the end, except when the string already had multiple newlines on the end". Or something. This is why C and Java don't bite here: it's trivial to say what their equivalent routines do. You can see the implementation as you read the description, and you can fathom all the consequences without a thought. And they're so trivial that you're unlikely to forget.

I've no idea why you'd want to be sloppy about whether a string ended in a newline or not. Why, if there were some special meaning to a final newline, you wouldn't want it explicit in your program.

The lesson? Always use print in a real Ruby program.

Why doesn't someone name a language after something on the low end of the Mohs scale. Talc, anyone? It even sounds like a Unix program.