comp.lang.ada
 help / color / mirror / Atom feed
From: Niklas Holsti <niklas.holsti@tidorum.invalid>
Subject: Re: Access types as parameters
Date: Sat, 15 Aug 2009 22:19:41 +0300
Date: 2009-08-15T22:19:41+03:00	[thread overview]
Message-ID: <4a870a5b$0$26302$4f793bc4@news.tdc.fi> (raw)
In-Reply-To: <c3wd5mpebbb7.srlcuddwxdfp.dlg@40tude.net>

Dmitry A. Kazakov wrote:
> On Fri, 14 Aug 2009 19:03:52 +0300, Niklas Holsti wrote:
> 
>> Or we don't agree on the formalism, which seems to be the case for you 
>> and me.
> 
> Once people agreed on a formalism there would be no place for
> discussions... (;-))

Perhaps in the ideal, yes. But formalisms in "design" are not yet that 
powerful or unambiguous :-)

>>> Why do you dispatch again, you already checked the tag.
>> Because this gives me the functionality I want, of course.
> 
> That is clear, but if you say that the functionality you wanted is
> re-dispatch itself, that could not justify it. There must be something else
> in it, which raises the question of design. You have implemented something
> using re-dispatch. My position is that it is a bad way to implement
> anything. You disagree... (:-))

Well, you still haven't shown me any convincing reason for calling it a 
bad design, because I don't accept your "type error" argument.

>>> The type is determined,
>> Of course not, only the point (within the class) of the implementation 
>> of the currently executing, (possibly) inherited operation (the caller) 
>> is determined. The actual type, as you well know, is any type in 
>> T'Class, although it is written "T" in the operation profile.
> 
> No, the actual type is T, just because the operation declaration tells so.

This seems to be the origin of our disagreement. You want to view the 
object as of type T, although at run-time it may be a T-view of an 
object of a derived type S. This means that you cannot redispatch. But 
this does not entitle you to call redispatching "bad" in general.

> If you are in the operation inherited by S from T and you don't want it to
> be T there, then why do have you inherited and not overridden it in S?
> Something must be wrong in it.

Not at all, it works perfectly for S. If I had overridden it for S, it 
would have exactly the same text as for T (except of course for the 
change in type name from T to S).

If the operation did *not* use redispatching, it would *not* work for T 
as well as for S, and I would have to override it for S.

> Are you saying that the reader must be constantly aware that the type of
> the actual parameter could be not the type the procedure deals with?

Yes, of course. Because of inheritance.

>> I suggest that you show how you would design the Divide-and-Conquer 
>> example that I described in my reply to Randy earlier today, and then we 
>> can compare the two designs.
> 
>    type Subproblem is abstract ...;
>    procedure Conquer (X : in out Subproblem) is abstract;
>    type List_Of_Subproblems is ...; -- Container type of Subproblem'Class
> 
>    type Problem is abstract ...;
>    function Divide (X : Problem) return List_Of_Subproblems is abstract;

Ok, good for discussing. This works, but has some drawbacks compared to 
a redispatching solution. Firstly, it needs new data structures 
(Subproblem and List_Of_Subproblems) which may require dynamic memory 
allocation if the Subproblem type is complex. Secondly, it is no longer 
possible to stop the Divide operation when the first solvable Subproblem 
is discovered. Thirdly, you now need a class-wide operation that invokes 
Divide and then Conquer for the given object of type T'Class.

Finally, a point that is not a drawback in my view, but should be in 
your view (as I understand it): there is still no guarantee that the 
actual invoked Divide operation and the actual invoked Conquer operation 
are defined for the same type; the actual T'Class object might inherit 
Divide from type T, and Conquer from type S.

Logically (but perhaps exaggerating a bit) you should consider this a 
type error because it is mixing the semantics of T and S. I'm sure you 
don't see this as a problem, probably because you assume that the 
semantics of T and S are sufficiently "compatible", being all in 
T'Class. But this is just the reason why I don't think that 
redispatching from Divide (T) to Conquer (S) is a type error.

> A better case for re-dispatch is an operation defined in terms
> of other operations.

Well, I do think that Divide, in my example, is defined in terms of 
other operations, namely Conquer, because Divide (in my design) finds 
the subproblems and calls Conquer on each subproblem. Perhaps I should 
have called the operation Divide_And_Conquer to make this clear in the 
name, sorry.

> For example x*n defined as x+...+x, n times. you want to have a
> standard version of *, but in some cases to have an ability to
> implement it specifically.

I think that is quite similar to the Divide/Conquer example.

> I am using a sort of this:
> 
>    procedure Add (X : in out Item; Y : Item);
>    procedure Mul (X : in out Item'Class; N : Positive);
> private
>    function Has_Accelerated_Mul (X : Item) return Boolean;
>    procedure Accelerated_Mul (X : in out Item; N : Positive);
> 
>    procedure Mul (X : in out Item'Class; N : Positive) is
>    begin
>       if Has_Accelerated_Mul (X) then
>          Accelerated_Mult (X, N);

Shudder (my turn :-). This is a kind of manually implemented overriding, 
where Accelerated_Mul sometimes "overrides" Mul. I much prefer to use 
the language-defined overriding of primitive operations, so I would make 
Mul primitive on Item, instead of class-wide, and override it with an 
accelerated version for those Item'Class types that allow it. This is 
probably faster, too :-)

One problem in your design is that someone can now mistakenly call 
Accelerated_Mul (X) even if Has_Accelerated_Mul (X) is False. Moreover, 
Has_Accelerated_Mul seems to depend on the particular object (X), not 
just on the type (Item). Or was this your intention?

> My empirical condition for all dispatching operations is that type tag
> resolution should move strictly towards the root, and never backwards. I.e.
> if you have a tag for T'Class,, you can narrow the set of candidates
> ultimately to the single type, but you never widen the set.

This rule defines a subset of Ada that you want to use. OK, but so far 
you have not convinced me that there is any benefit in this subset.

We are all struggling to find the small nuggets of correct programs 
hidden in the vast rockpile of incorrect programs. I can believe that 
your empirical condition is helpful to you, but I have not found any 
problems with redispatching.

I suggest that we agree to disagree and close here.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



  reply	other threads:[~2009-08-15 19:19 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-17  8:39 Access types as parameters Rick
2009-07-17 15:03 ` Adam Beneschan
2009-07-17 16:28   ` Hibou57 (Yannick Duchêne)
2009-07-17 23:25     ` rickduley
2009-07-18  1:03       ` Randy Brukardt
2009-07-19 22:57         ` rickduley
2009-07-20  0:10           ` John B. Matthews
2009-07-20  8:13           ` Dmitry A. Kazakov
2009-07-21  0:34           ` Randy Brukardt
2009-07-21 14:34           ` Adam Beneschan
2009-07-23  2:11             ` Stephen Leake
2009-08-11 23:41               ` Randy Brukardt
2009-08-12  2:22                 ` Stephen Leake
2009-08-13  1:06                   ` Randy Brukardt
2009-08-13  8:34                     ` Niklas Holsti
2009-08-13  9:15                       ` Dmitry A. Kazakov
2009-08-13 20:13                         ` Niklas Holsti
2009-08-13 21:07                           ` Dmitry A. Kazakov
2009-08-14  9:27                             ` Niklas Holsti
2009-08-14 10:36                               ` Dmitry A. Kazakov
2009-08-14 16:03                                 ` Niklas Holsti
2009-08-15  9:47                                   ` Dmitry A. Kazakov
2009-08-15 19:19                                     ` Niklas Holsti [this message]
2009-08-16  8:32                                       ` Dmitry A. Kazakov
2009-08-16  9:52                                         ` Niklas Holsti
2009-08-16 12:38                                           ` Dmitry A. Kazakov
2009-08-16 13:21                                             ` Niklas Holsti
2009-08-16 17:58                                               ` Dmitry A. Kazakov
2009-08-14  4:07                       ` Randy Brukardt
2009-08-14 10:22                         ` Niklas Holsti
2009-08-18 12:22                     ` Stephen Leake
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox