[Grace-core] reified generics -- good news / bad news

James Noble kjx at ecs.vuw.ac.nz
Thu Oct 6 04:06:41 PDT 2011


Hi all

so thinking about "new" & reified generics
  - the question from the minutes about "what does  Factory<Types>.new(args) mean"

well based on the current spec - explaining classes by expanding out to objects:

the basic expansion currently in the spec is:

def CatFactory = object { // the cat factory
    method new(aColour: Colour, aName: String) -> Cat {
        return object  { // the cat herself
            def colour : Colour := aColour
            def name : String := aName
            var miceEaten := 0
        }
     }
}

we could make it generic  (in "Colour" for some odd reason) just like this -
the trick here is the "new" method is generic, so you'd have to write
CatFactory.new<Colour>(Green, "mimi"): 

def CatFactory = object { // the cat factory
    var instanceCount := 0 
    method new<T>(aColour: T, aName: String) -> Cat[T]
                            where T <: Colour 
        {instanceCount := instanceCount + 1  
         return object  { // the cat herself, now generic
            def colour : T := aColour
            def name : String := aName
            var miceEaten := 0
        }
     }
}

this all seems straightforward, instanceCount would count
instances irrespective of their generic types.
But we'd have to write "CatFactory.new<Colour>(Green, "mimi")"
to make new objects.

we can get around that problem to write CatFactory<Colour>.new(Green, "mimi")
by making the CatFactory generic like this**:

def catFactoryMap =  Map<Type, CatFactory<Dynamic>>  // somewhat evil that Dynamic in there...

method CatFactory<T>  -> CatFactoryType<T> 
                          where T <: Colour 
 {return //  probably need a type assertion of some kind in here, but would never fail.
   catFactoryMap at(T) ifAbsentPut { 
    object { // generic cat factories :-)
    var instanceCount := 0 
    method new(aColour: T, aName: String) -> Cat[T] {
       instanceCount := instanceCount + 1 
       return object  { // the cat herself
            def colour : T := aColour
            def name : String := aName
            var miceEaten := 0
        }}
     }
  }
}

except I'm not quite sure this does what we want.  Certainly the "T"
generic parameter should be captured properly.
The first problem is that if we're not careful, every *invocation* of CatFactory<T>
would return a *new* CatFactory object.  (The instanceCount of
almost every factory will only ever be 1). To fix that,
I build a map from actual T values to objects (that's 
the catFactoryMap and what at()ifAbsentPut does)
effectively lazily creating the type-specific factories.
This would also mean that the instanceCount variable
in each type-specific factory would mean something useful - 
the map would assure there was only one 

So I think we can make this work too.  That's the Good News - 
we can do this at least two ways.   What's the bad news:

well, that especially the second case, but with a bit of thought, more generally
*when any program actually relies on reified generics - the program's
behaviour would be changed if the types were erased or all set to dynamic*

Basically two of our principles "reified generics" and "operational semantics
independent of types" doesn't seem to work. Or at least, they don't work
if your computation can ever depend on the value of the reified generics.
But if they can't, what's the value of reification?  As John B put it last week -
we're back to Erasure.  oops. 

=======


*assuming type declarations like this:

type Cat[T] = {
   colour -> T
   name -> String
   miceEaten -> Number
   miceEaten:= (_:Number) -> None
}

type CatFactoryType = {
  new<T>(_:T,_:String) -> Cat[T]
}

**assuming type declarations like this:

type Cat[T] = { // same as above
   colour -> T
   name -> String
   miceEaten -> Number
   miceEaten:= (_:Number) -> None
}

type CatFactoryType[T] = {  // different, now generic too
  new(_:T,_:String) -> Cat[T]
}


More information about the Grace-core mailing list