|
|
|
colinlema
|
I ran in to some spaghetti when looking at a C# program recently and
the issues were related to delegates/agents. When I hit these moments I think "What would Eiffel do?" and on a side topic realized features in Eiffel kind of lose their contracts and self-definition when turned in to an agent. Sure the contract still evaluates but there's nothing in an agent's signature that lets you know its contract. The code I was looking at also passes structures containing multiple delegates and I was observing that was essentially an interface. I know C# doesn't support explicit repeat inheritance so a class could never *be* multiple identical interfaces, it could only *contain* them. Eiffel classes are also limited to being polymorphically assigned to only one parent interface per type and defining the features used is through the `select' keyword. Could the inheritance relations of classes be named so you can specify exactly which interface to use? This seems like it would get rid of the need for agents all together and they could make use of better-defined deferred classes. class A inherit one: B rename proc as proc1 end two: B rename proc as proc2 end feature proc1 is do print ("Hello") end proc2 is do print ("There") end end deferred class B proc is deferred end end Features on A could be executed: local thing: A do -- Calls to the same feature thing.one.proc thing.proc1 -- Calls to the same feature thing.two.proc thing.proc2 end Just some thoughts. |
|
colinlema
|
Horrible idea? :D
--- In eiffel_software@..., "colinlema" <clemahieu@...> wrote: > > I ran in to some spaghetti when looking at a C# program recently and > the issues were related to delegates/agents. When I hit these moments > I think "What would Eiffel do?" and on a side topic realized features > in Eiffel kind of lose their contracts and self-definition when turned > in to an agent. Sure the contract still evaluates but there's nothing > in an agent's signature that lets you know its contract. > > The code I was looking at also passes structures containing multiple > delegates and I was observing that was essentially an interface. I > know C# doesn't support explicit repeat inheritance so a class could > never *be* multiple identical interfaces, it could only *contain* them. > > Eiffel classes are also limited to being polymorphically assigned to > only one parent interface per type and defining the features used is > through the `select' keyword. > > Could the inheritance relations of classes be named so you can specify > exactly which interface to use? This seems like it would get rid of > the need for agents all together and they could make use of > better-defined deferred classes. > > class A > inherit > one: B > rename > proc as proc1 > end > two: B > rename > proc as proc2 > end > > feature > proc1 is > do print ("Hello") end > proc2 is > do print ("There") end > end > > deferred class B > proc is > deferred end > end > > Features on A could be executed: > local > thing: A > do > > -- Calls to the same feature > thing.one.proc > thing.proc1 > > -- Calls to the same feature > thing.two.proc > thing.proc2 > end > > Just some thoughts. > |
||||||||||||||||||
|
Helmut Brandl
|
colinlema wrote:
> Horrible idea? :D > It is not clear to me what your proposal is. The example you gave does not show any advantage. Try to be more specific. I could imagine that your proposal conflicts with some rules of Eiffel. If you have a Descendant with multiple versions of an inherited feature from an ancestor and the Descendant conforms to the ancestor, proper select statements have to select a "dynamic bind version". This is a static property. It seems that you want to do the selection at runtime. But I am not sure. But try to give a better example in order to be able discuss it better. Helmut The Eiffel Compiler: http://tecomp.sourceforge.net > --- In eiffel_software@..., "colinlema" <clemahieu@...> wrote: > >> I ran in to some spaghetti when looking at a C# program recently and >> the issues were related to delegates/agents. When I hit these moments >> I think "What would Eiffel do?" and on a side topic realized features >> in Eiffel kind of lose their contracts and self-definition when turned >> in to an agent. Sure the contract still evaluates but there's nothing >> in an agent's signature that lets you know its contract. >> >> The code I was looking at also passes structures containing multiple >> delegates and I was observing that was essentially an interface. I >> know C# doesn't support explicit repeat inheritance so a class could >> never *be* multiple identical interfaces, it could only *contain* them. >> >> Eiffel classes are also limited to being polymorphically assigned to >> only one parent interface per type and defining the features used is >> through the `select' keyword. >> >> Could the inheritance relations of classes be named so you can specify >> exactly which interface to use? This seems like it would get rid of >> the need for agents all together and they could make use of >> better-defined deferred classes. >> >> class A >> inherit >> one: B >> rename >> proc as proc1 >> end >> two: B >> rename >> proc as proc2 >> end >> >> feature >> proc1 is >> do print ("Hello") end >> proc2 is >> do print ("There") end >> end >> >> deferred class B >> proc is >> deferred end >> end >> >> Features on A could be executed: >> local >> thing: A >> do >> >> -- Calls to the same feature >> thing.one.proc >> thing.proc1 >> >> -- Calls to the same feature >> thing.two.proc >> thing.proc2 >> end >> >> Just some thoughts. >> >> > > > > ------------------------------------ > > Yahoo! Groups Links > > > > |
||||||||||||||||||
|
colinlema
|
Hopefully this isn't dynamic, it should be static. The interface
names wouldn't be used by the runtime system, only when compiling (I think) The problem: Let's use the example of a GUI with event handlers. If a GUI widget contains a list of handlers when the widget event fires, why is that a list of agents instead of a list of deferred classes? Existing way: ---- class A create make feature make do create handlers.make end handlers: LINKED_LIST [PROCEDURE [ANY, TUPLE []]] end ---- ---- class MAIN create make feature make local test: A do create test.make test.handlers.put (agent thing1) test.handlers.put (agent thing2) end thing1 do io.put_string ("Handler 1") end thing2 do io.put_string ("Handler 2") end end ---- Replacing agents with deferred classes it could be: ---- class HANDLER feature handle is deferred end end ---- ---- class A create make feature make do create handlers.make end handlers: LIST [HANDLER] end ---- ---- class MAIN inherit HANDLER rename handle as thing1 end select thing1 end HANDLER rename handle as thing2 end create make feature make is local test: A do create test.make test.handlers.put (current) -- test.handlers.put (agent thing2) No equivalent! end thing1 do io.put_string ("Handler 1") end thing2 do io.put_string ("Handler 2") end end ---- but as can be seen, MAIN can't put its two handlers in to `test: A' because classes can only be polymorphically handled by one super class per type. Handlers `thing1' and `thing2' would have to be put in their own class files. Named ancestors allow us to solve this problem (I think). It looks like composition but is actually inheritance; uniform access. ---- class HANDLER feature handle is deferred end end ---- ---- class A feature handlers: LIST [HANDLER] end ---- ---- class MAIN inherit one: HANDLER --Named inheritance rename handle as thing1 end select thing1 end two: HANDLER --Named inheritance rename handle as thing2 end create make feature make is local test: A do create test.make test.handlers.put (current.one) --Specifying which superclass to use test.handlers.put (current.two) end thing1 do io.put_string ("Handler 1") end thing2 do io.put_string ("Handler 2") end end ---- Existing polymorphism could be considered a subset of named polymorphism with anonymous inheritance. Existing way: ---- class A end class B inherit A -- Anonymous inheritance end class MAIN make local test: A do test := create {B} --It's implied that B conforms to A in only one way end ---- this is equivalent to: ---- class A end class B inherit anonymous: A --Named inheritance end class MAIN make local: A do test := create {B}.anonymous end ---- --- In eiffel_software@..., Helmut Brandl <helmut.brandl@...> wrote: > > colinlema wrote: > > Horrible idea? :D > > > It is not clear to me what your proposal is. The example you gave does > not show any advantage. Try to be more specific. > > I could imagine that your proposal conflicts with some rules of Eiffel. > If you have a Descendant with multiple versions of an inherited feature > from an ancestor and the Descendant conforms to the ancestor, proper > select statements have to select a "dynamic bind version". This is a > static property. It seems that you want to do the selection at runtime. > But I am not sure. > > But try to give a better example in order to be able discuss it better. > > Helmut > The Eiffel Compiler: http://tecomp.sourceforge.net > > > > --- In eiffel_software@..., "colinlema" <clemahieu@> > > > >> I ran in to some spaghetti when looking at a C# program recently and > >> the issues were related to delegates/agents. When I hit these moments > >> I think "What would Eiffel do?" and on a side topic realized features > >> in Eiffel kind of lose their contracts and self-definition when turned > >> in to an agent. Sure the contract still evaluates but there's nothing > >> in an agent's signature that lets you know its contract. > >> > >> The code I was looking at also passes structures containing multiple > >> delegates and I was observing that was essentially an interface. I > >> know C# doesn't support explicit repeat inheritance so a class could > >> never *be* multiple identical interfaces, it could only *contain* them. > >> > >> Eiffel classes are also limited to being polymorphically assigned to > >> only one parent interface per type and defining the features used is > >> through the `select' keyword. > >> > >> Could the inheritance relations of classes be named so you can specify > >> exactly which interface to use? This seems like it would get rid of > >> the need for agents all together and they could make use of > >> better-defined deferred classes. > >> > >> class A > >> inherit > >> one: B > >> rename > >> proc as proc1 > >> end > >> two: B > >> rename > >> proc as proc2 > >> end > >> > >> feature > >> proc1 is > >> do print ("Hello") end > >> proc2 is > >> do print ("There") end > >> end > >> > >> deferred class B > >> proc is > >> deferred end > >> end > >> > >> Features on A could be executed: > >> local > >> thing: A > >> do > >> > >> -- Calls to the same feature > >> thing.one.proc > >> thing.proc1 > >> > >> -- Calls to the same feature > >> thing.two.proc > >> thing.proc2 > >> end > >> > >> Just some thoughts. > >> > >> > > > > > > > > ------------------------------------ > > > > Yahoo! Groups Links > > > > > > > > > |
||||||||||||||||||
|
Helmut Brandl
|
Ok, now it is clear what you mean.
I don't know whether that conflicts with anything. Some thoughts: Currently in Eiffel polymorphic attachment is just an attachment of an object to an entity. The entity type has to be a conformant descendant. But the entity refers (we talk about reference objects) to the object to which it is attached. The object is not changed by the attachment operation. Speaking in terms of implementation: An entity is a pointer to the object. Your proposal implies that attachment has some additional information. The entity could be attached to the same object in different ways (what you call via different interfaces). That information has to be stored somewhere. Because further assigments can happen, the only way is (at least as I can imagine) to store it in the object (but without changing the object!!). I.e. you need some intermediate object refering to the original object and reflecting the way in which the attachment happened. If this is correct, the next question is: Are these intermediate objects agents in disguise? But before going on further let's see, if I have understood you correctly and if you have some other idea how to store the information about the different attachment status (In C++ you can point to subobjects; but therefore you cannot decide replication or sharing for features individually, you have to decide it for the whole parent with replication being the default. Maybe you have something like C++ in mind.). Helmut The Eiffel Compiler: http://tecomp.sourceforge.net colinlema wrote: > Hopefully this isn't dynamic, it should be static. The interface > names wouldn't be used by the runtime system, only when compiling (I > think) > The problem: Let's use the example of a GUI with event handlers. If a > GUI widget contains a list of handlers when the widget event fires, > why is that a list of agents instead of a list of deferred classes? > > Existing way: > > ---- > class A > create make > feature > make > do > create handlers.make > end > handlers: LINKED_LIST [PROCEDURE [ANY, TUPLE []]] > end > ---- > > ---- > class MAIN > create make > feature > make > local > test: A > do > create test.make > test.handlers.put (agent thing1) > test.handlers.put (agent thing2) > end > thing1 > do > io.put_string ("Handler 1") > end > thing2 > do > io.put_string ("Handler 2") > end > end > ---- > > Replacing agents with deferred classes it could be: > > ---- > class HANDLER > feature > handle is > deferred > end > end > ---- > > ---- > class A > create make > feature > make > do > create handlers.make > end > handlers: LIST [HANDLER] > end > ---- > > ---- > class MAIN > inherit > HANDLER > rename > handle as thing1 end > select thing1 end > HANDLER > rename > handle as thing2 end > create make > feature > make is > local > test: A > do > create test.make > test.handlers.put (current) > -- test.handlers.put (agent thing2) No equivalent! > end > thing1 > do > io.put_string ("Handler 1") > end > thing2 > do > io.put_string ("Handler 2") > end > end > ---- > > but as can be seen, MAIN can't put its two handlers in to `test: A' > because classes can only be polymorphically handled by one super class > per type. Handlers `thing1' and `thing2' would have to be put in > their own class files. > > Named ancestors allow us to solve this problem (I think). It looks > like composition but is actually inheritance; uniform access. > > ---- > class HANDLER > feature > handle is > deferred > end > end > ---- > > ---- > class A > feature > handlers: LIST [HANDLER] > end > ---- > > ---- > class MAIN > inherit > one: HANDLER --Named inheritance > rename > handle as thing1 end > select thing1 end > two: HANDLER --Named inheritance > rename > handle as thing2 end > create make > feature > make is > local > test: A > do > create test.make > test.handlers.put (current.one) --Specifying which superclass to use > test.handlers.put (current.two) > end > thing1 > do > io.put_string ("Handler 1") > end > thing2 > do > io.put_string ("Handler 2") > end > end > ---- > > Existing polymorphism could be considered a subset of named > polymorphism with anonymous inheritance. > > Existing way: > > ---- > class A > end > > class B > inherit > A -- Anonymous inheritance > end > > class MAIN > make > local > test: A > do > test := create {B} --It's implied that B conforms to A in only one way > end > ---- > > this is equivalent to: > > ---- > class A > end > > class B > inherit > anonymous: A --Named inheritance > end > > class MAIN > make > local: A > do > test := create {B}.anonymous > end > ---- > > --- In eiffel_software@..., Helmut Brandl > <helmut.brandl@...> wrote: > >> colinlema wrote: >> >>> Horrible idea? :D >>> >>> >> It is not clear to me what your proposal is. The example you gave does >> not show any advantage. Try to be more specific. >> >> I could imagine that your proposal conflicts with some rules of Eiffel. >> If you have a Descendant with multiple versions of an inherited feature >> from an ancestor and the Descendant conforms to the ancestor, proper >> select statements have to select a "dynamic bind version". This is a >> static property. It seems that you want to do the selection at runtime. >> But I am not sure. >> >> But try to give a better example in order to be able discuss it better. >> >> Helmut >> The Eiffel Compiler: http://tecomp.sourceforge.net >> >> >> >>> --- In eiffel_software@..., "colinlema" <clemahieu@> >>> > wrote: > >>> >>> >>>> I ran in to some spaghetti when looking at a C# program recently and >>>> the issues were related to delegates/agents. When I hit these >>>> > moments > >>>> I think "What would Eiffel do?" and on a side topic realized features >>>> in Eiffel kind of lose their contracts and self-definition when >>>> > turned > >>>> in to an agent. Sure the contract still evaluates but there's >>>> > nothing > >>>> in an agent's signature that lets you know its contract. >>>> >>>> The code I was looking at also passes structures containing multiple >>>> delegates and I was observing that was essentially an interface. I >>>> know C# doesn't support explicit repeat inheritance so a class could >>>> never *be* multiple identical interfaces, it could only *contain* >>>> > them. > >>>> Eiffel classes are also limited to being polymorphically assigned to >>>> only one parent interface per type and defining the features used is >>>> through the `select' keyword. >>>> >>>> Could the inheritance relations of classes be named so you can >>>> > specify > >>>> exactly which interface to use? This seems like it would get rid of >>>> the need for agents all together and they could make use of >>>> better-defined deferred classes. >>>> >>>> class A >>>> inherit >>>> one: B >>>> rename >>>> proc as proc1 >>>> end >>>> two: B >>>> rename >>>> proc as proc2 >>>> end >>>> >>>> feature >>>> proc1 is >>>> do print ("Hello") end >>>> proc2 is >>>> do print ("There") end >>>> end >>>> >>>> deferred class B >>>> proc is >>>> deferred end >>>> end >>>> >>>> Features on A could be executed: >>>> local >>>> thing: A >>>> do >>>> >>>> -- Calls to the same feature >>>> thing.one.proc >>>> thing.proc1 >>>> >>>> -- Calls to the same feature >>>> thing.two.proc >>>> thing.proc2 >>>> end >>>> >>>> Just some thoughts. >>>> >>>> >>>> >>> >>> ------------------------------------ >>> >>> Yahoo! Groups Links >>> >>> >>> >>> >>> > > > > ------------------------------------ > > Yahoo! Groups Links > > > > |
||||||||||||||||||
|
colinlema
|
I see now, so a reference would have to be a reference + (information)
and the information would define which named inheritance relation it should use. Since the object could be referenced differently by different clients this information would have to be stored on the client side. Anyway, I don't write the compilers or define the language, but it seemed like an interesting idea. --- In eiffel_software@..., Helmut Brandl <helmut.brandl@...> wrote: > > Ok, now it is clear what you mean. > > I don't know whether that conflicts with anything. > > Some thoughts: > > Currently in Eiffel polymorphic attachment is just an attachment of an > object to an entity. The entity type has to be a conformant descendant. > But the entity refers (we talk about reference objects) to the > which it is attached. The object is not changed by the attachment > operation. Speaking in terms of implementation: An entity is a pointer > to the object. > > Your proposal implies that attachment has some additional information. > The entity could be attached to the same object in different ways (what > you call via different interfaces). That information has to be stored > somewhere. Because further assigments can happen, the only way is (at > least as I can imagine) to store it in the object (but without changing > the object!!). I.e. you need some intermediate object refering to the > original object and reflecting the way in which the attachment happened. > > If this is correct, the next question is: Are these intermediate > agents in disguise? > > But before going on further let's see, if I have understood you > correctly and if you have some other idea how to store the information > about the different attachment status (In C++ you can point to > subobjects; but therefore you cannot decide replication or sharing for > features individually, you have to decide it for the whole parent with > replication being the default. Maybe you have something like C++ in mind.). > > Helmut > The Eiffel Compiler: http://tecomp.sourceforge.net > > > > colinlema wrote: > > Hopefully this isn't dynamic, it should be static. The interface > > names wouldn't be used by the runtime system, only when compiling (I > > think) > > The problem: Let's use the example of a GUI with event handlers. If a > > GUI widget contains a list of handlers when the widget event fires, > > why is that a list of agents instead of a list of deferred classes? > > > > Existing way: > > > > ---- > > class A > > create make > > feature > > make > > do > > create handlers.make > > end > > handlers: LINKED_LIST [PROCEDURE [ANY, TUPLE []]] > > end > > ---- > > > > ---- > > class MAIN > > create make > > feature > > make > > local > > test: A > > do > > create test.make > > test.handlers.put (agent thing1) > > test.handlers.put (agent thing2) > > end > > thing1 > > do > > io.put_string ("Handler 1") > > end > > thing2 > > do > > io.put_string ("Handler 2") > > end > > end > > ---- > > > > Replacing agents with deferred classes it could be: > > > > ---- > > class HANDLER > > feature > > handle is > > deferred > > end > > end > > ---- > > > > ---- > > class A > > create make > > feature > > make > > do > > create handlers.make > > end > > handlers: LIST [HANDLER] > > end > > ---- > > > > ---- > > class MAIN > > inherit > > HANDLER > > rename > > handle as thing1 end > > select thing1 end > > HANDLER > > rename > > handle as thing2 end > > create make > > feature > > make is > > local > > test: A > > do > > create test.make > > test.handlers.put (current) > > -- test.handlers.put (agent thing2) No equivalent! > > end > > thing1 > > do > > io.put_string ("Handler 1") > > end > > thing2 > > do > > io.put_string ("Handler 2") > > end > > end > > ---- > > > > but as can be seen, MAIN can't put its two handlers in to `test: A' > > because classes can only be polymorphically handled by one super class > > per type. Handlers `thing1' and `thing2' would have to be put in > > their own class files. > > > > Named ancestors allow us to solve this problem (I think). It looks > > like composition but is actually inheritance; uniform access. > > > > ---- > > class HANDLER > > feature > > handle is > > deferred > > end > > end > > ---- > > > > ---- > > class A > > feature > > handlers: LIST [HANDLER] > > end > > ---- > > > > ---- > > class MAIN > > inherit > > one: HANDLER --Named inheritance > > rename > > handle as thing1 end > > select thing1 end > > two: HANDLER --Named inheritance > > rename > > handle as thing2 end > > create make > > feature > > make is > > local > > test: A > > do > > create test.make > > test.handlers.put (current.one) --Specifying which superclass to use > > test.handlers.put (current.two) > > end > > thing1 > > do > > io.put_string ("Handler 1") > > end > > thing2 > > do > > io.put_string ("Handler 2") > > end > > end > > ---- > > > > Existing polymorphism could be considered a subset of named > > polymorphism with anonymous inheritance. > > > > Existing way: > > > > ---- > > class A > > end > > > > class B > > inherit > > A -- Anonymous inheritance > > end > > > > class MAIN > > make > > local > > test: A > > do > > test := create {B} --It's implied that B conforms to A in only one way > > end > > ---- > > > > this is equivalent to: > > > > ---- > > class A > > end > > > > class B > > inherit > > anonymous: A --Named inheritance > > end > > > > class MAIN > > make > > local: A > > do > > test := create {B}.anonymous > > end > > ---- > > > > --- In eiffel_software@..., Helmut Brandl > > <helmut.brandl@> wrote: > > > >> colinlema wrote: > >> > >>> Horrible idea? :D > >>> > >>> > >> It is not clear to me what your proposal is. The example you gave > >> not show any advantage. Try to be more specific. > >> > >> I could imagine that your proposal conflicts with some rules of Eiffel. > >> If you have a Descendant with multiple versions of an inherited feature > >> from an ancestor and the Descendant conforms to the ancestor, proper > >> select statements have to select a "dynamic bind version". This is a > >> static property. It seems that you want to do the selection at runtime. > >> But I am not sure. > >> > >> But try to give a better example in order to be able discuss it better. > >> > >> Helmut > >> The Eiffel Compiler: http://tecomp.sourceforge.net > >> > >> > >> > >>> --- In eiffel_software@..., "colinlema" <clemahieu@> > >>> > > wrote: > > > >>> > >>> > >>>> I ran in to some spaghetti when looking at a C# program > >>>> the issues were related to delegates/agents. When I hit these > >>>> > > moments > > > >>>> I think "What would Eiffel do?" and on a side topic realized features > >>>> in Eiffel kind of lose their contracts and self-definition when > >>>> > > turned > > > >>>> in to an agent. Sure the contract still evaluates but there's > >>>> > > nothing > > > >>>> in an agent's signature that lets you know its contract. > >>>> > >>>> The code I was looking at also passes structures containing > >>>> delegates and I was observing that was essentially an interface. I > >>>> know C# doesn't support explicit repeat inheritance so a class could > >>>> never *be* multiple identical interfaces, it could only *contain* > >>>> > > them. > > > >>>> Eiffel classes are also limited to being polymorphically assigned to > >>>> only one parent interface per type and defining the features used is > >>>> through the `select' keyword. > >>>> > >>>> Could the inheritance relations of classes be named so you can > >>>> > > specify > > > >>>> exactly which interface to use? This seems like it would get rid of > >>>> the need for agents all together and they could make use of > >>>> better-defined deferred classes. > >>>> > >>>> class A > >>>> inherit > >>>> one: B > >>>> rename > >>>> proc as proc1 > >>>> end > >>>> two: B > >>>> rename > >>>> proc as proc2 > >>>> end > >>>> > >>>> feature > >>>> proc1 is > >>>> do print ("Hello") end > >>>> proc2 is > >>>> do print ("There") end > >>>> end > >>>> > >>>> deferred class B > >>>> proc is > >>>> deferred end > >>>> end > >>>> > >>>> Features on A could be executed: > >>>> local > >>>> thing: A > >>>> do > >>>> > >>>> -- Calls to the same feature > >>>> thing.one.proc > >>>> thing.proc1 > >>>> > >>>> -- Calls to the same feature > >>>> thing.two.proc > >>>> thing.proc2 > >>>> end > >>>> > >>>> Just some thoughts. > >>>> > >>>> > >>>> > >>> > >>> ------------------------------------ > >>> > >>> Yahoo! Groups Links > >>> > >>> > >>> > >>> > >>> > > > > > > > > ------------------------------------ > > > > Yahoo! Groups Links > > > > > > > > > |
||||||||||||||||||
| Free Forum Powered by Nabble | Forum Help |