OK, I’ve been thinking (always dangerous after 11 pm).
Class-level entities can be accessed via a double-colon.
No big mystery:
File::open(…)
File::SEPARATOR
Happily, a class method can also be accessed via a dot:
File.open(…)
But a constant can’t:
File.SEPARATOR # syntax error
First, why is it this way?
I think because scoping must necessarily have its own notation - consider
the following:
class T; end
class C
class T; end
def T; end
def m
C.new
::T
end
end
If you were to use a ‘.’ in place of the ‘::’ here, you’d end up with an
ambiguous expression, as the following is perfectly legal:
C.new
.T
There’s also the fact that if you eliminated double-colon in favor of dot
you’d basically have to force all methods to start with a lowercase letter:
class C
class T; end
def T; end
end
Should the method T in this case completely replace the class T? What about
all of the constants nested within T? Of course, since methods starting with
uppercase letters are generally frowned upon, that might not affect that
much code, but it would still be a pretty drastic change.
Now, as for using ‘::’ for calling singleton methods… well, as far as I
can tell, you can use it for calling any method, singleton or not:
irb(main):001:0> Object:
:to_s
=> “#Object:0x2ba4098”
irb(main):002:0> Object:
:inspect
=> “#Object:0x2ba1770”
irb(main):003:0> String:
:strip
=> “”
irb(main):004:0>
So, if one uses both double-colon and dot in one’s code for method access,
it is necessarily in an arbitrary fashion. For some reason that I do not
fully understand, I find using ‘::’ for class method access aesthetically
pleasing:
String::new
I tell myself that I like it because it makes the same code tell me more
about itself at a glance, but I’m not sure about that. I think it might have
more to do with the fact that it’s more consistent looking (to me) when I’m
chaining constants together to access a class method:
Test::Unit::UI::Console::TestRunner::run(suite)
Anyhow, that’s my current take on the matter, subject to vacillation at any
point in the future. I actually just switched over to doing things this way
a few months back after seeing it in someone else’s code.
Personally, I don’t like the :: anyway, as it reminds me
of C++.
Well, I didn’t use to like underscores in method names and local variables,
but now I find them quite appealing. After that experience I’ve determined
to not judge the notation of one language just because it’s like (or not
like) the notation of another language, unless the notation in question has
serious practical downsides. It wouldn’t do to have a language like C++ or
Java spoiling my Ruby bliss 
By the way, for those who are wondering, this is possible:
class File
def self.SEPARATOR
File::SEPARATOR
end
end
File.SEPARATOR # “/”
Even though it looks almost like recursion. Hmm, that raises the question
of
why/how this works.
From a bit of irb exploration it would appear that this works because ‘::’
will always bind to a constant in preference of a method, while ‘.’ is
guaranteed to bind to a method.
And another issue is: One could write a little module that, when
included in a
class, exposed all the class’s constants in this way. Within five minutes
I had it
“almost” working. I’ll bet someone in another timezone or with more
caffeine could
have it working in three. Anyone?
I guess it reminds me of writing a module to allow one to access all
under_score methods as camelCase: you can do it (love that Ruby!), but would
it just confuse folks who read your code? I think I would be confused.
It’s been fun thinking about this… thanks for the brain food, Hal!
Nathaniel
<:((><
···
Hal Fulton [mailto:hal9000@hypermetrics.com] wrote: