Class variables only bound in methods following them

Project:GNU Smalltalk
Status:won't fix

Might be by design, but it's confusing… I suppose the first B resolves to a non-existent global ?

Object subclass: Fail [
    a [ stdout << 'a:' << B; nl ]
    B := 'hi there'.
    c [ stdout << 'c:' << B; nl ]

st> Fail new a; c
c:hi there
a Fail


#1 submitted by Paolo Bonzini on Fri, 03/27/2009 - 06:30

I agree that it's confusing, but "stealing" a binding from Undeclared would not be possible for two reasons:

  • you risk introducing a binding from one class to another
  • you cannot handle the case in which two different classes have the same undeclared variable, and then the variable turns out to be a class variable only in one of the two.

The way to fix this would be to give a warning upon defining the class variable if the variable can be found in Undeclared. Usually the naming conventions for globals and class variables are different enough that it should not give many false positives.

#2 submitted by Damien Pollet on Fri, 03/27/2009 - 10:34

What about going through the class definition for class variables first, then compile the methods? So at least inside the A subclass: B [ … ] block, the compiler would only "Undeclare" only what's really not there.

#3 submitted by Paolo Bonzini on Fri, 03/27/2009 - 10:36

That would mean you have to keep potentially the entire class in memory, right? Right now the parse tree of GNU Smalltalk is never deeper than a method.

#4 submitted by Damien Pollet on Fri, 03/27/2009 - 13:37

Indeed. I'm thinking like in pure file-based languages where you want to organize the file arbitrarily and use lexical scope. I'm not entirely clear how variable pools are resolved in other Smalltalks anyway. Here class variables just seemed like a nice way to emulate constants for synopsis, help text, and so on :)

#5 submitted by Paolo Bonzini on Sat, 04/25/2009 - 10:29
Status:active» invalid

> Here class variables just seemed like a nice way to emulate constants for synopsis, help text, and so on :)

Yes, you just have to place them before they're used. :-)

Ruby and Python behave like this too, I think it is safe to declare this invalid.

Thanks for raising the point anyway!

#6 submitted by Damien Pollet on Sun, 04/26/2009 - 15:23
Status:invalid» active

Actually, ruby behaves like I want:

   def hello
     puts HELLO
   # calling hello would fail here
   HELLO = "Hello, world!"

the variable is bound like it should even if the reference is before the declaration (well actually it's declared when it's first seen in the method), but of course if you evaluate it before it's been initialized, then you get an exception.

#7 submitted by Paolo Bonzini on Mon, 11/02/2009 - 18:46
Status:active» postponed

Given that Ruby is also a bit inconsistent, I'll leave the bug in the database, but I don't plan about working on it anytime soon.

#8 submitted by Holger Hans Pet... on Tue, 01/29/2013 - 20:10
Status:postponed» active

Can we close it? I don't think we will implement it and with the other fileout syntaxes one needs to declare the class variable early as well?

#9 submitted by Paolo Bonzini on Wed, 01/30/2013 - 09:38
Status:active» won't fix

We could force the class variables to come before any method. That would still have problems in the "extend" case.

I also thought about restricting the grammar to have a constant on the right side. This would simplify exporting to other dialects. However, there is really no restriction because you can use ##(...) to treat anything as a constant.

So in the end it is really a case of "if it hurts, don't do it"...

User login