Thread overview | |||||
---|---|---|---|---|---|
|
December 04, 2003 [RT] Ramblings of a Mad Man: Let me cast a spell... | ||||
---|---|---|---|---|
| ||||
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 Re: [RT] Ramblings of a Mad Man: Let me cast a spell... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Berin Loritsch | "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 Re: [RT] Ramblings of a Mad Man: Let me cast a spell... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mark Brudnak | 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. |
Copyright © 1999-2021 by the D Language Foundation