[Grace-core] initialisation & checking

James Noble kjx at ecs.vuw.ac.nz
Sat Apr 27 00:06:46 PDT 2013


Hi Andrew

so reflecting on things while packing - I thought:
even if the O'CAML rule is the "Right Thing" - why would
we want to bake that into the language spec?

(the O'CAML rule is basically that self may not be used
in code in object constructors or field initialisers or blocks
inside either --- its as if that code ran in the containing scope)

We otherwise allow programs to try to access uninitialised variables
and request the wrong messages on objects - and our implementation
has to pay a price for both those decisions. Are initialisation errors
really that much worse - or the conceptual costs that high - 
that we should place this restriction on all programs?
Isn't that too Wilsonian?  What about GW Bush who just wants his 
code to run?

or more pragmatically, what about me? When I want to write:

def parenTypeExpression = rule { lParen ~ typeExpression ~ rParen } 

featuring initialisers requesting a bunch of methods on self, 
requesting other methods to those request results, 
and registering a block (to avoid the recursion issues).

  * * * * * * * * * * * * * * * * * * *

A more subtle argument - more difficult to refute - is that 
most of the code in those object constructor bodies especially
will run at the wrong time. We don't want them to run while
the object may be uninitialised, we want them to run as soon
as they are ready - as soon as *all* fields in the whole object 
are initialised, and there's *no easy way* to specify that.

// pseudo-Grace syntax contrasting O'CAMLs field initialisers & 
// initializer blocks 

class Superclass {
  def colour = "red"          // field initialiser
  initalizer {this.register}   // initializer block, 
                                                // happens after bottommost subclass fields all initialised 
  method onRegistration { .. do stuff .. }
}

class Subclass {
  def borderColour = "Green"
  method onRegistration is override  { ... use borderColour }
}


O'CAML's initialiser blocks run just once, as soon as the whole
object's fields - including any subclass parts - are initialised
and *can* refer to self.  I think Dart's constructor *bodies* 
have the same rule (contrast Dart's field initialisers which cannot refer
to self, like O'CAML's field initialisers, and are all run before 
constructor bodies).

This code again runs in two (or more) phases:
 - build the object structure
 - initialize all fields top down order
     those initialisers run in the surrounding scope, don't have "this"
 - run all initializer blocks, top down order.

I don't think it is possible to program up that generally in Grace. 
We could borrow the syntax, we could build a list of blocks cached somewhere,
but I can't see how we can get the desired semantics - 
block initialisers should be called only once when the a whole object transitions
from "template" or "initialised"/"partially initialised" to "ground object".


  * * * * * * * * * * * * * * * * * * *

I'm not sure what all this means. Perhaps:

  - we add in initialiser blocks. They'd be advanced, they're really only
        needed in abstract objects that are planned to be inherited from
  - we otherwise run open code/ field initialiser/ create other blocks 
         in the object scope (i.e. they can access self, as it is now)
 - Andrew can have a checker that bans references to stuff in the 
         immediately enclosing object being initialised that he's welcome
         to run in Wilsonian mode.

J



More information about the Grace-core mailing list