Thread overview
[RT] Ramblings of a Mad Man: Let me cast a spell...
Dec 04, 2003
Berin Loritsch
Dec 06, 2003
Mark Brudnak
Dec 08, 2003
Berin Loritsch
December 04, 2003
The talk about casting and templates made me think of a feature that I am not
sure has been discussed in any language development, but I could definitely use
it.  It takes the concept of templates even further--removing the need for a
large majority of the type of castings that I have to perform.

Long and short of it is that I would suggest a strongly typed "properties" type
of object.  Before I get into the nitty gritty of what it does, let me first
explain the need:

In the Apache Avalon project, we supply components to client components using
a ServiceManager.  The ServiceManager provides a way to look up and retrieve
a type of component.  All the services are bound to a particular name, so any
time the client component looks up a particular name, it will be the same type
of component.  Period.  We would love to use generics, but in all known
implementations of generics, you can only assign types to all the objects
stored.  For instance:

map<string, void*>;

In C++ this would create a map where the key had to be a string, and the
returned value could be anything.  In Java we are not so lucky, the Map
object binds Objects to the lookup value and to the return value.  To be
fair, the Object type has all that the Map needs to determine the hashcode
value and whether two keys are the same.  Polymorphism is used to finetune
those details.

The problem is on the client side where I know what I am looking up, and
the type I need:

CrisisManager crisis = (CrisisManager)
        serviceManager.lookup(CrisisManager.ROLE);

Even with generics, this is the best I could hope for with the solutions
currently available.

What I *really* need is to bind a type to the lookup name so that when I
retern a value from a lookup service it will always return the same type
of object.  In fact if I can guarantee this, then I can solve most of my
needs for strong typing and losing the cast operator.

The solution would be sort of a dynamic struct.  Like dynamic arrays (already
implemented), the dynamic struct would add new members that have a strong name
and stong type bound to it.  Call it properties or something, I don't really
mind what the final name is:

properties foo;

// code to assign the properties
foo.bar<Baz> = newBaz();
foo.crisisManager<CrisisManager> = getCrisis();

// later on in the client code
void doClientThings(properties services)
{
    services.bar.doBazThing();
    services.crisisManager.findOpenCrises();

    // throws an IllegalAccess exception (it is unassigned)
    services.unassigned.illegal();
}

Any subsequent assignments to a particular type have to be of that type.
For example:

foo.bar<Bar> = newBar();

// throws an IllegalType exception (it is a Baz type, not a Bar type)
foo.bar = newBaz();

And trying to reassign a type is also illegal once it has been set:

foo.bar<Bar>;

// throws an IllegalOperation exception (it has already been identified)
foo.bar<SomethingElse>;


And to perfectly round out the entire proposal it would be even more killer to
make the dynamic struct readonly after a particular point.  For example, if
I have the container code set up this dynamic struct, I won't want any of the
clients to reassign the objects/components I have painstakenly added to it.
Nor would I want them to add new assignments.  So if there is a way to freeze
the thing, it would totally rock.  Perhaps a special purpose property that
once the boolean is changed the entire struct becomes hardened like this:

properties foo;
foo.bar<Baz> = newBaz();
foo.crisisManager<CrisisManager> = getCrisis();
foo.writeable = false;

// all of these throw IllegalAccess exception
foo.bar = anotherBaz();
foo.subjectManager<SubjectManager = getSubjects();
foo.writable = true;

Or perhaps a "method" would be the way to go.  Perhaps assigning it as a const
is enough.  Dunno.  However this thing would help out alot.

IMPLEMENTATION DETAILS
----------------------
This is only one of the many possible ways to implement this feature.
Internally this would be an map<string, struct{Class type; Object value;}> that
is hidden by the compiler.  (I am thinking easiest to implement from my POV).
A lookup would be translated to something like this:

struct{Class type; Object value;} entry = map[entryName];
userVariable = (entry.type)entry.value;

Something along those lines would be good enough.  This is not the only way to
implement this thing at all.  Perhaps you could come up with new and exciting
ways yourself.

CAVEAT
------
This does mean that type checking has to be done at runtime instead of compile
time.  This is an unavoidable side effect.  Perhaps some compile time checking
could be done if D had some C# style attributes.  For example:

[RequiredEntry(example, foo)]
[RequiredEntry(example, bar)]
void myMethod(properties example)
{
    // no errors
    example.foo.doSomething();
    example.bar.doSomething();

    // compile time error
    example.baz.doSomething();
}

Also if those same attributes were available at runtime, it could help the
container code (i.e. initializing code) to build the properties object with
the expected values.  In my experience, any one client would only need a few
of these attributes.  Of course, it would be cumbersome to have to type all
these entries for every method that uses the type.  To that end, attribute sets
would be even better.  But that is another topic altogether.

December 06, 2003
"Berin Loritsch" <bloritsch@d-haven.org> wrote in message news:bqned2$fgn$1@digitaldaemon.com...
> The talk about casting and templates made me think of a feature that I am
not
> sure has been discussed in any language development, but I could
definitely use
> it.  It takes the concept of templates even further--removing the need for
a
> large majority of the type of castings that I have to perform.
>
> Long and short of it is that I would suggest a strongly typed "properties"
type
> of object.  Before I get into the nitty gritty of what it does, let me
first
> explain the need:
>
> In the Apache Avalon project, we supply components to client components
using
> a ServiceManager.  The ServiceManager provides a way to look up and
retrieve
> a type of component.  All the services are bound to a particular name, so
any
> time the client component looks up a particular name, it will be the same
type
> of component.  Period.  We would love to use generics, but in all known implementations of generics, you can only assign types to all the objects stored.  For instance:
>
> map<string, void*>;
>
> In C++ this would create a map where the key had to be a string, and the returned value could be anything.  In Java we are not so lucky, the Map object binds Objects to the lookup value and to the return value.  To be fair, the Object type has all that the Map needs to determine the hashcode value and whether two keys are the same.  Polymorphism is used to finetune those details.
>
> The problem is on the client side where I know what I am looking up, and the type I need:
>
> CrisisManager crisis = (CrisisManager)
>          serviceManager.lookup(CrisisManager.ROLE);
>
> Even with generics, this is the best I could hope for with the solutions currently available.
>
> What I *really* need is to bind a type to the lookup name so that when I retern a value from a lookup service it will always return the same type of object.  In fact if I can guarantee this, then I can solve most of my needs for strong typing and losing the cast operator.
>

What I think you are saying is that you would like to look up a type based on a string like this,

class myClass = repository.lookup("aClassName") ;

object anObject = myClass.new  ;

If this is what you mean, then you are talking about a metaclass, like Smalltalk?  A class is just another object of type "MetaClass".

> The solution would be sort of a dynamic struct.  Like dynamic arrays
(already
> implemented), the dynamic struct would add new members that have a strong
name
> and stong type bound to it.  Call it properties or something, I don't
really
> mind what the final name is:

You can instantiate a meta class at run time to create a new class.

class newClass = new class ;
newClass.addInterface("foo") ;
newClass.addInterface("bar") ;

>
> properties foo;
>
> // code to assign the properties
> foo.bar<Baz> = newBaz();
> foo.crisisManager<CrisisManager> = getCrisis();
>
> // later on in the client code
> void doClientThings(properties services)
> {
>      services.bar.doBazThing();
>      services.crisisManager.findOpenCrises();
>
>      // throws an IllegalAccess exception (it is unassigned)
>      services.unassigned.illegal();
> }
>
> Any subsequent assignments to a particular type have to be of that type. For example:
>
> foo.bar<Bar> = newBar();
>
> // throws an IllegalType exception (it is a Baz type, not a Bar type)
> foo.bar = newBaz();
>
> And trying to reassign a type is also illegal once it has been set:
>
> foo.bar<Bar>;
>
> // throws an IllegalOperation exception (it has already been identified)
> foo.bar<SomethingElse>;
>
>
> And to perfectly round out the entire proposal it would be even more
killer to
> make the dynamic struct readonly after a particular point.  For example,
if
> I have the container code set up this dynamic struct, I won't want any of
the
> clients to reassign the objects/components I have painstakenly added to
it.
> Nor would I want them to add new assignments.  So if there is a way to
freeze
> the thing, it would totally rock.  Perhaps a special purpose property that once the boolean is changed the entire struct becomes hardened like this:
>
> properties foo;
> foo.bar<Baz> = newBaz();
> foo.crisisManager<CrisisManager> = getCrisis();
> foo.writeable = false;

That is the beauty of access functions and properties.  This feature does not need to be built into the language.
>
> // all of these throw IllegalAccess exception
> foo.bar = anotherBaz();
> foo.subjectManager<SubjectManager = getSubjects();
> foo.writable = true;
>
> Or perhaps a "method" would be the way to go.  Perhaps assigning it as a
const
> is enough.  Dunno.  However this thing would help out alot.
>
> IMPLEMENTATION DETAILS
> ----------------------
> This is only one of the many possible ways to implement this feature. Internally this would be an map<string, struct{Class type; Object value;}>
that
> is hidden by the compiler.  (I am thinking easiest to implement from my
POV).
> A lookup would be translated to something like this:
>
> struct{Class type; Object value;} entry = map[entryName];
> userVariable = (entry.type)entry.value;
>
> Something along those lines would be good enough.  This is not the only
way to
> implement this thing at all.  Perhaps you could come up with new and
exciting
> ways yourself.
>
> CAVEAT
> ------
> This does mean that type checking has to be done at runtime instead of
compile
> time.  This is an unavoidable side effect.  Perhaps some compile time
checking
> could be done if D had some C# style attributes.  For example:
>
> [RequiredEntry(example, foo)]
> [RequiredEntry(example, bar)]
> void myMethod(properties example)
> {
>      // no errors
>      example.foo.doSomething();
>      example.bar.doSomething();
>
>      // compile time error
>      example.baz.doSomething();
> }
>
> Also if those same attributes were available at runtime, it could help the container code (i.e. initializing code) to build the properties object
with
> the expected values.  In my experience, any one client would only need a
few
> of these attributes.  Of course, it would be cumbersome to have to type
all
> these entries for every method that uses the type.  To that end, attribute
sets
> would be even better.  But that is another topic altogether.
>


December 08, 2003
Mark Brudnak wrote:
> "Berin Loritsch" <bloritsch@d-haven.org> wrote in message
> news:bqned2$fgn$1@digitaldaemon.com...
> 
>>The talk about casting and templates made me think of a feature that I am
> 
> not
> 
>>sure has been discussed in any language development, but I could
> 
> definitely use
> 
>>it.  It takes the concept of templates even further--removing the need for
>>What I *really* need is to bind a type to the lookup name so that when I
>>retern a value from a lookup service it will always return the same type
>>of object.  In fact if I can guarantee this, then I can solve most of my
>>needs for strong typing and losing the cast operator.
>>
> 
> 
> What I think you are saying is that you would like to look up a type based
> on a string like this,
> 
> class myClass = repository.lookup("aClassName") ;
> 
> object anObject = myClass.new  ;
> 
> If this is what you mean, then you are talking about a metaclass, like
> Smalltalk?  A class is just another object of type "MetaClass".

Not quite.  WHat I want is pretty much a dynamic struct with strong typing.
Essentially, I want to have one class populate the struct and another class
to use it.  I am not trying to have the client class worry about instantiation
of the new object.  All I want to do to use the class is this:

Crisis[] crises = myDynStruct.crisisManager.getCrises();
Connection conn = myDynStruct.dataSource.getConnection();

It is already populated by something else.

THe important thing here is to get away from having to cast everything or pass
it as a weaker type.