From: Clemens Hintze Date: 2000-01-12T11:44:56+01:00 Subject: [ruby-talk:01129] Class variables... David Suarez de Lis writes: > Hi all, Hi you, :-) > I am brand new to Ruby's world, but I find it pretty > interesting... :) then let me take the chance to welcome you to our interesting world of Ruby. :-) > I have a doubt, though, I haven't been able to solve through > testing or documentation... No problem, this is the reason for that this mailing list was created for (officially. In reality matz has created this list to address my handicap, that I has learned the wrong language and not Japanese; because most of the gurus are on the japanese mailing list; but we are on the way to change this ;-)))) > Say I have a class person and a variable @population. First mistake here. The sign '@' denotes *instance* variables. Class variables, however, are not instance variables. In fact Ruby has no true class variables yet (but it has class methods :-). I don't know, if that is going to change in future ... matz?) > > class Person > @population = 0 > def new(the_name = nil) > @name = the_name > @Person::population += 1 > end > end May I suggest to let me insert a small script below, that will deal with your class? You could store it into a file and execute it. I don't know, if you have already recognized it, but Ruby has *true* GC (mark and sweep schme). Normally it is not very predictable, when an object will be reclaimed! For that reason, I have inserted 'GC.start' calls to invoke start GC at a certain point. Under normal circumstances you would not have to call it by your own! A further disadvantage of this *true* GC (the 1st one is the unpredictability, if you will count it as disadvantage) is, that finalization of objects is a little bit complicate to understand. There is no automatic call to a certain method forseen for an object being subject to deletion like in other languages like Python, Perl or Java! You have to use 'ObjectSpace.define_finalizer' to attach a finalizer Proc instance, that will be called during GC for that object! BUT PAY ATTENTION, YOU MUST NOT STORE ANY REFERENCE TO THAT OBJECT INTO SUCH A FINALIZER PROC. If you would do so, the GC would think, that the object is needed yet, and will never be deleted therefore. This problem is comparable with the circular reference problem in Reference Counting Garbage Collectors. But please bear also in mind, that if you create a Proc instance (via: proc, lambda or Proc.new) *within* a method, an invisible variable 'self', pointing to the instance for that this method was called for, will also be stored in that Proc object, becaus the Proc instance resembles a closure that will remember the whole context that was valid during instantiation/creation. So that is the reason, why you have to use class methods for creating/generation lambda expressions to announce for finalization. It is a little bit confusing, isn't it? ;-) Perhaps the script makes things clear: ----------------------8X---------------------------- #!/bin/env ruby require "final" class Person Population = [0] # Following method will be called automatically during instanciation def initialize(name) @name = name Population[0] += 1 print name, " is born ...\n" ObjectSpace.define_finalizer(self, Person::died(name)) # Pay attention!!! Following would not work! Reason is implicite # 'self' pointer created by 'lambda'! # ObjectSpace.define_finalizer(self, lambda{ Population[0] -= 1 }) end # Follwing class method is a Proc instance generator ;-) def Person.died(who) Proc.new do print who, " died ...\n" Population[0] -= 1 end end # Also a class method for reporting the size of the population. def Person.report if Population[0] > 0 print "Population: #{Population[0]} persons.\n" else print "No population at all!\n" end end end folks = [] for name in "A".."Z" folks << Person.new(name) end Person.report while not folks.empty? folks.shift # Remove first Person from Array GC.start # Comment that line to see a difference end GC.start # Comment that line to see a difference Person.report exit 0 ----------------------8X---------------------------- > Ie. I want to be able to access that class variable from > objects... Also, I assume END {} allows us to put conditions for GC? > Like END { @Person::population -= 1 } No! END is like system call 'atexit' in C! > > thanks for your help, > d@ It was my pleasure. I know, that my explanations sound a little bit confusing, perhaps. If you have any questions, do not hesitate to ask! :-) ciao, \cle