How about a typed Dynamic?

I have an application in which I need to se Dynamic, but I want strong typing. I want the compiler and the IDE to be able to check that I am using the right fields to access a given object, but I want that access mediated by a Dynamic (a proxy) object.

I have never liked the Java Proxy mechanism as I have to define things twice, and that is always a recipie for problems. Dynamic does away with the interface - which is good - but looses the strong typing - which is bad.

But it occurs to me that a typed Dynamic, i.e Dynamic[T], would allow for the best of both worlds. I get to intercept the field and method references, and the compiler can make sure I don’t ask for the wrong thing or assume it returns the wrong type.

Now changing Dynamic to add [T] would be difficult as it would not be backward compatible, but adding a new Dynamic (either TypedDynamic or maybe scala.typed.Dynamic) which did take a type would solve the problem.

The definition of TypedDynamic would be:-

trait TypedDynamic[T] extends T

and the compiler/IDE would then treat the object that extended TypedDynamic as though it were a T for all cases where a field or method reference was used but would use the Dynamic mechanism to deliver the field and method references to the code.

David

Just for my understanding, why not use the static type T if you know it?

At the point of definiton I know there is a T, but not the value of T.

So I have a base class for a group of objects, and set of reference objects that represent the boundaries for external storage purposes. The reference objects are the ones in which I use Dynamic.

Lets take an example. I am a farmer, and we have a herd of dairy cows. So our list of objects is going to be something of the form:-

Herd - with details of the herd and references to Address objects
Animal - One per animal, contains list of offspring, list of milking records, list of medical interventions
MilkingRecod - quantity and quality of milk
Address - postal or geographical address of the dairy
MedicalRecord - details of condition being treated, medicine used, outcome

So the Herd contains a list of references to animals, the Animals contain references to their parents, and a list of offspring, etc.

So I would like to be able to write in the Herd class (just the animal list and address):-

class Herd {
var animals:List[Reference[Animal]]
var address:Reference[Address]
}

The reference is used a bit like a lazy variable, so we only fetch the object from the object store when we need it. It contains a transient field referencing the target object.

To complete the picture we need a separate dataset, the invoicing system. The medicine used in the MedicalRecord will have been bought, and there will be an invoice in the invoicing system. The herdsman does not need to see the invoicing details, but does need the invoice number and the medicine name from the invoice. So the reference object also acts as a cache holding values that are needed for display, but using the actual value when viewed by the farm manager who has both datasets. So my generic Reference object needs to be able to react to whatever remote object it is defined to be attached, but I want the compiler to be able to check that when a Reference[Invoice] is used then the list of value fields and methods is the sum of those in Reference and those in Invoice.

Is that any clearer?

Perhaps an ordinary implicit conversion would fit your purpose?

trait Reference[T] {
  lazy val target: T
}
object Reference {
  implicit def ref2t[T](ref: Reference[T]): T = ref.target
}

If you want calls to Dynamic to be checked statically it would not make much sense anymore to call it ‘dynamic’.

No, I have obviously not explained the problem properly.

Consider the case where the object I am referencing is remote, so I need to take the “call” to the object and package it, and pass it over a communications link and get a reply. In this case I need the Dynamic so that I get the calls to package, and I need it typed so that the compiler can check I am using it correctly.

I am trying to avoid having a separate interface. Defining things in two places is a recipy for problems. Java Proxys do exactly this, and that is what I am trying to avoid.

Dynamic as it currently exist is curiously out of step with the otherwise strongly typed nature of Scala, all I am suggesting is that having a typed Dynamic would bring it into line with the rest of the language.

There is a way, but it’s not the simplest. You can implement methods of the Dynamic trait using macros and perform the type-checking in the macro definitions. For example, Shapeless does something like this: https://github.com/milessabin/shapeless/blob/0663667f5fc8c1bbbf30b5926f12a978bd97b137/core/src/main/scala/shapeless/hlists.scala#L116

FWIW Dotty has something similar, called Selectable.
http://dotty.epfl.ch/docs/reference/changed/structural-types.html