tags:

views:

796

answers:

2

Simple question, but one that I've been curious about...is there a functional difference between the following two commands?

String::class
String.class

They both do what I expect -- that is to say they return Class -- but what is the difference between using the :: and the .?

I notice that on those classes that have constants defined, IRB's auto-completion will return the constants as available options when you press tab after :: but not after ., but I don't know what the reason for this is...

+30  A: 

The . operator basically says "send this message to the object". In your example it is calling that particular member. The :: operator "drills down" to the scope defined to the left of the operator, and then calls the member defined on the right side of operator.

When you use :: you have to be referencing members that are defined. When using . you are simply sending a message to the object. Because that message could be anything, auto-completion does not work for . while it does for ::.

Joseph Daigle
+9  A: 

Actually, auto-completion does work for .. The completion options are found by calling #methods on the object. You can see this for yourself by overriding Object.methods:

>> def Object.methods; ["foo", "bar"]; end
=> nil
>> Object.[TAB]
Object.foo  Object.bar
>> Object.

Note that this only works when the expression to the left of the . is a literal. Otherwise, getting the object to call #methods on would involve evaluating the left-hand side, which could have side-effects. You can see this for yourself as well:

[continuing from above...]
>> def Object.baz; Object; end
=> nil
>> Object.baz.[TAB]
Display all 1022 possibilities? (y or n)

We add a method #baz to Object which returns Object itself. Then we auto-complete to get the methods we can call on Object.baz. If IRB called Object.baz.methods, it would get the same thing as Object.methods. Instead, IRB has 1022 suggestions. I'm not sure where they come from, but it's clearly a generic list which isn't actually based on context.

The :: operator is (also) used for getting a module's constants, while . is not. That's why HTTP will show up in the completion for Net::, but not for Net.. Net.HTTP isn't correct, but Net::HTTP is.

Peeja