Obscure and Ugly Perlisms in Ruby

Posted by Nick Sieger

So, it’s well known that Ruby owes a debt to its predecessor Perl, although some (maybe many) question whether we should repay that debt or even go so far as to put Perl on trial and excise those elements which somehow haphazardly survived the generation gap. It turns out the evidence is mixed.

Update: I use the word “obscure” in the title because, in my experience, they are obscure. “Ugly” is pure opinion, but this is my blog, after all.

Exhibit A: BEGIN/END

Update: Yes, yes, this is an awk-ism, not a perlism, strictly speaking. And I don’t deny its usefulness for pure scripting tasks. I just don’t see its utility in a larger application.

END { puts " Bye! " } puts " Processing... " BEGIN { puts " One moment while I start your program " }

Output:

One moment while I start your program Processing... Bye!

Why would any sane Ruby programmer do this? Have you ever seen a use for BEGIN that isn’t met by simply executing code at the top level of the main program? Geez, BEGIN even has its own node in the AST!

And how about END? If you really need to hook into interpreter shutdown, just use Kernel#at_exit . (In fact, Rubinius currently uses END simply as an alias for at_exit .)

Exhibit B: <> (ARGF)

Thank goodness we didn’t get the diamond operator in Ruby, but we did get ARGF as a replacement. Though obscure, it actually turns out to be useful. Consider this program, which prepends copyright headers in-place (thanks to another perlism, -i ) to every file mentioned on the command-line. Any other creative uses of ARGF out there?

Header = DATA . read ARGF . each_line do | e | puts Header if ARGF . pos - e . length == 0 puts e end

Exhibit C: The Flip-flop

This is a weird beast. I didn’t even know of its existence until Charlie was complaining about having to compile it properly. Apparently we have Perl to thank for this nonsense as well (and, indirectly, sed ). With the exception of the sed-ism, I’m not convinced it adds any value -- in fact the code usually ends up looking more verbose.

This program, when run with itself as an argument, prints out everything between BEGIN and END.

ARGF . each_line do | line | if ( line =~ / ^# BEGIN /)..( line =~ / ^# END /) puts line end end

This snippet is a long-hand way to do 5.upto(10) {|i| puts i} .

i = 5 while ( i == 5 )...( i == 10 ) do puts i i += 1 end

Exhibit D: Output from defined?

Not sure if this came from Perl.

The basic need for defined? in a dynamic language is unquestionable. Instead, I meant to highlight the fact that defined? returns a string value here, which is strange.

Constant = " Constant " @ivar = [ 1 , 2 , 3 ] integer = 10 puts " const : #{defined?(Constant)} " puts " ivar : #{defined?(@ivar)} " puts " global: #{defined?($0)} " puts " local : #{defined?(integer)} " puts " expr : #{defined?(Constant + integer)} "

Running this code produces:

const : constant ivar : instance-variable global: global-variable local : local-variable expr : method

Perl at least is sane enough to return true or false for its own defined operator. But method ? Looking at the source, I see also expression , local-variable(in-block) , assignment , class variable , true , false , and self . But why would this output be useful? As if it isn’t already plainly obvious what is defined? .

Any other obscure features in Ruby that you love to hate?