Working on a Ruby program I was looking to move some state data from instance variables to class variables, it dawned on me that while instance variables are auto-vivified (if you try to read them "without initializing" them, they are automatically initialized to nil), class variables are not - and this looks very inconsistent to me (compared to most Ruby syntax which is very consistent).
Sample program:
class Test
  def id
    @id.to_i
  end
  def id=(i)
    @id = i
  end
  def nextid
    self.id = id + 1
  end
end
t = Test.new
puts t.nextid #=> 1
puts t.nextid #=> 2
In which case, when calling Test::id, if @id was not initialized, Ruby will auto-vivify it to nil (after which I to_i it to get 0).
Now I decide that I want the running ID to be shared across Test instance, so I rewrite it like this:
class Test
  def id
    @@id.to_i
  end
  def id=(i)
    @@id = i
  end
  def nextid
    self.id = id + 1
  end
end
t = Test.new
puts t.nextid
puts t.nextid
Should work the same, I thought, but no:
NameError: uninitialized class variable @@id in Test
But this workaround works (!?) :
class Test
  def id
    (@@id ||= 0).to_i
  end
  def id=(i)
    @@id = i
  end
  def nextid
    self.id = id + 1
  end
end
t = Test.new
puts t.nextid #=> 1
puts t.nextid #=> 2
(granted, after doing lazy init to 0 I can drop the to_i, but I left it for consistency).
It looks like Ruby understands "lazy initialization" and treats it as the magic needed to not throw NameError - even though ||= is supposedly just syntactic sugar to x = x || val (which BTW doesn't work for initing class variables, thanks for asking).
How come?
 
     
    