tags:

views:

124

answers:

3

I am learning Ruby and found this code sample in some documentation:

require 'find'

  total_size = 0

  Find.find(ENV["HOME"]) do |path|
    if FileTest.directory?(path)
      if File.basename(path)[0] == ?.
        Find.prune       # Don't look any further into this directory.
      else
        next
      end
    else
      total_size += FileTest.size(path)
    end
  end

The purpose is to sum up the file sizes of all files in a tree, excluding directories that start with a dot. The line "if File.basename(path)[0] == ?." is obviously performing the directory name test. I would have written it like this:

if File.basename(path)[0] == "."

What does "?." do? (Could be a typo, I suppose.) I have not seen this syntax described elsewhere.

+1  A: 

It means to return the character code of the next character. In Ruby, saying string[0] gives you a character code, so it's like saying is the first character a ".".

Interestingly, it means that expressions like ???!?!?? are perfectly legal in Ruby.

Take a look here.

Anthony Mills
I have yet to find that part of Ruby that is "easy to learn".
Paul Chernoch
I don't know if it's incredibly easy to learn, but it does have a lot of really nice aspects to its syntax. I'm primarily a JavaScript programmer and there are many times I wish I had Ruby's block syntax or its "everything returns a value" orthogonality.
Anthony Mills
that's a totally random use of the word orthogonality.
Peter
+2  A: 

It is a shorthand for the ASCII code point of the "." character. See the documentation on numeric literals in the Ruby syntax.

>> ?.
=> 46
>> ?a
=> 97
Brian Campbell
Note that this behavior changed in Ruby 1.9. In Ruby 1.9, `?a` returns the string `"a"`, which is consistent with indexing a string, which also returns a string instead of a number.
newacct
+7  A: 

?. returns the ASCII value of the dot. You can put pretty much any char after the question mark to get its ASCII value, like ?a or ?3 or ?\\, etc. The reason they are not comparing it to the string "." is that when you index into a string, you get the ASCII value of the char at that index rather than the char itself. To get the char at a certain index you can use [0, 1] as the index. So the options are:

if File.basename(path)[0] == ?.

Or:

if File.basename(path)[0, 1] == "."

Or even:

if File.basename(path)[0].chr == "."
yjerem
Thank you! I now recall reading about that operator. This Perl programmer has a lot to unlearn.
Paul Chernoch