From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,a8d137db7a5f6c81 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!postnews.google.com!f14g2000cwb.googlegroups.com!not-for-mail From: "per" Newsgroups: comp.lang.ada Subject: Re: OO problem: Performing actions on messages (very long, sorry) Date: 22 Dec 2004 09:42:31 -0800 Organization: http://groups.google.com Message-ID: <1103737351.196460.85450@f14g2000cwb.googlegroups.com> References: <1103723394.299024.314670@c13g2000cwb.googlegroups.com> <13465377.hrn0RlrJV7@linux1.krischik.com> NNTP-Posting-Host: 138.14.239.132 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1103737357 10795 127.0.0.1 (22 Dec 2004 17:42:37 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 22 Dec 2004 17:42:37 +0000 (UTC) User-Agent: G2/0.2 Complaints-To: groups-abuse@google.com Injection-Info: f14g2000cwb.googlegroups.com; posting-host=138.14.239.132; posting-account=e84-wQ0AAADeDLnjH5yWqnRMVsJLfQJg Xref: g2news1.google.com comp.lang.ada:7172 Date: 2004-12-22T09:42:31-08:00 List-Id: Hi Dimitri, thanx for your answers. Sorry for the yucky code/text. All indentation and line breaks was screwed up:( I'm using google groups (for the first time). Not very user friendly. Had to compose this answer in a separate file and manually paste in the citations so this answer is also a bit yucky... >> Each action child shall be able to "do something" with a message in the >> virtual (is that the Ada term?) procedure Execute. > >No. It is called "primitive operation". OK. But is there no distinction between operations that may dispatch and those those who cannot? Execute, for example, may be a primitive operation of each child regardless of if the parent has declared it or not. So "primitive operation" doesn't tell that dispatching will be possible or not, right? Maybe "dispatching" is the distinction? >> The action Action.Override serves as an example in this post. This >> action shall override a field in a message. > >One cannot override a field. Presently Ada's inheritance model is a type >extension one. I.e. you can add a field, but not replace it with another. No! I was unclear. I'm not trying to override anything in that sense. The messages are basically records filled with values. It's the _values_ in the existing message structures the Action.Override is supposed to override: type Instance is new Message.Instance with record A : Float; B : Integer; ... end record; ... Somewhere some mechanism assigns the initial values: M1 : Message.M1.Instance; Put_A(M1, 1.0); Put_B(M1, 1); ... Later on, an override action shall be able to override these values by basically doing: Put_A(M1, Some_Other_Value_Stored_In_The_Action); again! Other messages may record the entire message and send it to some place else, or just extract some specific data field and pass along etc. >> All actions are created and then enqueued in certain action queues in a >> preparation phase and then executed (real-time) in the execution phase. >> The messages are both created and transported through the system in the >> execution phase. > >> In order to store the value to override with, and where to put it when >> performing the override, the Action.Override stores an override >> argument (like a Float for instance) and an access to the proper >> Put-procedure (like Put_A(M : in out Message.M1.Instance; A : Float)) >> for a certain message class instance (the specific message the action >> shall operate upon). The Put procedure takes as arguments the message >> instance and a value to put. The procedure name defines what message >> field to put the value into, such as Put_A for field A. > >It is too late. Basically Put should be a primitive operation of >Message...Instance. But when you pass a type as a formal generic parameter >it is already frozen, which in other words means that you cannot define a >primitive Put for it. You can do instead: > >generic > type ArgumentType is private; -- Type extension >package Message.Extender is > type Instance is new Message.Instance with record > Extension : ArgumentType; > end record; > procedure Put (M : Instance; A : ArgumentType); > -- This is a "method" of Instance now > >procedure Put (M : Instance; A : ArgumentType) is >begin > M.Extension := A; >end Put; You're saying I should replace every single field in every message record with an extension as above? I sort of get what you mean, but not entirely. I can't see how my "complex" message records would look like. Each message consists of many variables and sub-records. I don't think this is what I look for. It feels like you're answering another question here... maybe due to the above misunderstanding? >> The type of the field to override and the type of the message are >> generic parameters in the Action.Override package/class, so there's one >> instantiation of Action.Override for each message type and override >> type: > >> package M1_Float_Override_Action is new Action.Override >> (ArgumentType => Float, >> MessageType => Message.M1.Instance); > >> There's another abstract parent-class, Message, and non-abstract child >> classes Message.M1, Message.M2 etc. > >It is not clear what are you going to achieve by that. It will not be >dynamically polymorphic anyway as long as ArgumentTypes are not derived >from the same base. So any possible gain = 0, IMO. Correct. No polymorphy (at least not with this action-stuff). But all messages has common data and behaviours that I handle in the abstract base-class. So there's the gain. >> Each child message has its own set of, non-virtual, Put procedures that >> writes the contents of the message. The message contents is a record >> with arbitrary width, depth and types. > >If Put is not dispatching, what the use of it. In particular, why ":=" does >not fit? I want to assign values to fields in the messages from the override actions. How could this be done with ":=" only? I will not implement an action for EACH field in EACH message. I would love to make Put dispatching but how would a procedure look like that can assign a value to any field in a record? (Yes, I'm still stuck with that record...) >> There will also be a nice general mechanism that basically gets any >> type of message, applies any actions enqueued for it and then puts the >> message away. It feels like this should be possible with Ada mechanisms >> such as inheritage, polymorphy and generics but, I kind of doubt it >> now... > >It is definitely possible: > >package Messages is > type Message is > abstract new Ada.Finalization.Limited_Controlled with private; > procedure Execute (This : in out Message) is abstract; > > type Messages_Queue is > [abstract] new Ada.Finalization.Limited_Controlled with private; > -- Abstract if there should be different implementations of queues > procedure Enqueue > ( Queue : in out Messages_Queue; > Item : in out Message'Class > ) [is abstract]; >private > ... >end Messages; > >package Messages.My_Messages is > type My_Message is new Message with private; > procedure Finalize (This : in out Message); -- How to destruct > procedure Initialize (This : in out Message); -- How to construct > procedure Execute (This : in out Message); -- What to be done > procedure Put_A (This : in out Message; A : Something); > ... Ugh, I don't get it. How could the message know what to do in Execute? There may be 0 or 5 or 500 actions to be taken on each message. The messages do not exist when the actions are defined and hence can not be prepared with that information. Where/how do you store the values to override with for example...? Maybe this too is an effect of the initial misunderstanding? But I was enlighted by some other stuff in your example though :) >> Code >[...] > >> 1. Why does this not work? > >The expected type is MessageType as the compiler tells. MessageType is a >generic formal type. The compiler does not know of any its possible >relationships with Message.Instance. It is just a type: > >generic > type MessageType is private; > >It is not even tagged. I see. But the dispatching call "Message.Print(M.all)" works and that procedure expects as a parameter a concrete instance within Message.Instance'Class. It too gets this unknown MessageType yet the compiler doesn't whine. What's the difference? >> 2. Shouldn't a conversion from T11 stored in a T1'Class variable, to a >> T11 variable be OK of T11 is a child of T1 (checked during run-time)? > >Yes. If it is not, then Constraint_Error is propagated. Yay, I've got something right! :) >> The information needed is of course present in M.all, otherwise >> dispatching wouldn't be possible. (I have tested dispatching with the >> call Message.Print(M.all) commented out in the example and i works >> fine.) > >The information carrier is called "type tag". Each T'Class object has type >tag in it. OK. >> Note that making every Put-procedure virtual is not an option since >> they by nature are unique to each message. > >> 3. Are there any problems connected to that I use an access to a >> procedure? > >Basically, that it is not much OO. Primitive operations (virtual methods) >are for that. > >> 4. Is the generic type MessageType causing the problem? The MessageType >> is supposed to be a specific sub-class of Message, hence a member of >> Message'Class so... > >Yes. > >> 5. Have I designed completely wrong? > >Mmm, it is too complex to my taste. I have an impression that you dealt too >much with C++ templates. (:-)) Hehe, actually I've most been programming standard C... :) But I have (very varying) experience from OO languages such as TurboPascal (back in the 80's), C++, Ada95 and Java. >> 6. Do you have any suggestions on how to solve this problem in a good >> way? > >Message = Action to me. Even if there are some constraints like that >several actions to be executed in a defined order, I would stick to this >model using containers of actions. Would you still after my clarification? Cause I'm not really with you there just yet. You're most welcome to explain what you mean further. Thanks for your effort! I'm taking a Christmas break for a couple of days now... Regards Per