0x11 – …and a Happy New Year

for all of you. Before you enter the New Years Day frenzy, here are the results of last week’s puzzler. (Haven’t been a big secret anyways: every one with a Ruby interpreter could know in the meantime. Yes, that means you!)

What is the output of the following?

~ > irb
>> puts false or 1
false
=> 1
>> puts false || 1
1
=> nil
>> puts false | 1
true
=> nil

You see, or binds weaker than everything else, more or less. Consequentyl, “puts false or 1” prints false, but because puts returns nil the value of the expression would be 1.

What is the output of the following?

For similar reasons – “and” binds pretty weak as well:

~ > irb
>> puts 1 and false
1
=> nil
>> puts 1 && false
false
=> nil
>> 

What is the result of

puts File.dirname("foo.bar")     # "."
puts File.dirname("/foo.bar")   # "/"
puts File.dirname("/foo.bar/")  # "/"

Would you have expected that?

How many times…

this script file wishes you a merry X-Mas three times:

puts "Merry XMas!"
require __FILE__
require File.dirname(__FILE__) + "/" + File.basename(__FILE__)

Even though “require” loads a file only once, it determines whether or not a file has already been loaded by the parameter to rquire. So “a.rb” and “./a.rb” are differenet files with respect to “require” – even though both filenames refer to the same file, as we humans are well aware. That means, if one of your source files must not be loaded more than once – for whatever reason – you must do something like

unless defined?(THIS_FILE_ALREADY_LOADED)
THIS_FILE_ALREADY_LOADED=true
  ...
end

And how many times does this script?

puts "Merry XMas!"
require __FILE__
require File.dirname(__FILE__) + "/" + File.basename(__FILE__)

Dir.mkdir "a" rescue nil
require File.dirname(__FILE__) + "/a/../" + File.basename(__FILE__)

This script will at some point crash with a “no such file to load” exception. When require loads a file, the __FILE__ value will be the parameter passed to require, and this one gets prepended “/a/../” in each turn. Which results in growing filenames, that still refer to the same file. But at some point the operating system will choke and refuse to resolve a filename like this, because the OSes imüose a limit on filename length and a limit on directory references in a filename.

And when running via ‘ruby script/runner‘?

script/runner apparently doesn’lt load the file via require. That results in the __FILE__ value set to “(eval)”, which usually doesn’t refer to an existing file. Remind yourself, that using the __FILE__ value is not always safe, as you can see here.

A Happy New Year to all of you!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s