views:

180

answers:

2

Ok, so everyone knows that capitalised identifiers are seen to be ‘constant’ in Ruby.

However, it is possible to assign a new value to constants, so the following works

class A
  def self.hi; "hi"; end
end
class B
  def self.hi; "ho"; end
end
A.hi # => "hi"
B.hi # => "ho"
A = B
#  warning: already initialized constant A
# => B
A.hi # => "ho"

and also does assigning to a lowercase identifier work:

a = B
a.hi # => "ho"

However, the internal name is set to ‘B’ in all cases and the new identifier names are also only referencing ‘B’.

But if it’s technically okay for the identifier to have a lowercase name, why is this restriction on the internal name for the class? It can’t be that it needs to be constant, because it isn’t constant; so the other reason could be that lowercase identifiers have a different scope. But then: why not having a class with lowercase scope?

I’m wondering because the parser even allows for method names in unicode and such, so it seems strange that for classes it’s so much more restricted.

A: 

The interpreter needs one way to find out if it is a Class name or a member variable of the current class/module.

The interpreter has to lookup class names in a global hash table while the member variables are in the class hash table. Local variables are different as they can be resolved by the interpreter without looking up hash tables at all (they have precedence over member variables).

And the only thing the interpreter knows about an identifier are the characters. Therefore there is the notational difference. Thats also the reason why global variables have a preceding $ and class variables an @ character. For this the interpreter has other hash tables it has to search.

Other script languages have similar restrictions, for example PHP needs a dollar in front of each variable.

Lothar
Member variables (aka instance variables) always start with `@`. Class variables start with `@@`. An identifier starting with a lower case letter is either a local variable or a method name.
sepp2k
+1  A: 

As you said, the name of a class is that of the first constant it has been assigned to. You can only use constants with the class keyword because it has been decided that the class keyword should only be used to create named classes.

The rationale probably being that allowing local variables would confuse uses, who would use class lowercase_class_name, not knowing the difference between lower case and upper case identifiers and then wonder why the classname was not visible everywhere (i.e. why def foo() lowercase_class_name.new end did not work).

By making the default way to create classes specific to constants, classes defined this way will be visible everywhere and there is at least a suggestion that the value associated with that name should not change (i.e. you get a warning otherwise).

People who know what they're doing can still do local_variable = Class.new { ... } if they need to.

sepp2k
Ok, I kind of understand that classes with lowercase scope would be too confusing if used with the `class` keyword. Although I must say that the rule that the class gets its name from the first constant it is assigned to can be similarly confusing.
Debilski