comp.lang.ada
 help / color / mirror / Atom feed
* Pb with use of redefined "=" operator
@ 1998-11-03  0:00 Fran�oise & Herv� BITTEUR
  1998-11-04  0:00 ` Mats Weber
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Fran�oise & Herv� BITTEUR @ 1998-11-03  0:00 UTC (permalink / raw)


I just run in a problem when combining :
- Ada.Strings.Bounded where '=' operator is redefined,
- A so far correct generic package (old Ada83 code) importing a private
(non-limited) type.

The problem is that any instantiation of the generic package will use
the "predefined" equality operator provided with any non-limited type,
rather than the specific definition related to Ada.Strings.Bounded.
Which leads to unexpected results on some occasions.

I have attached a very simplified example to illustrate the situation.
An obvious fix is to modify the spec of the generic package to
explicitly import a definition of '=' :
   with function "=" (L, R : in Item) return Boolean is <>;
And the redefined version if any (or the predefined one if none) will
then be used.

But what puzzles me is that :
1/ No warning is raised by the compiler (how could it be otherwise ?)
2/ Correct code (till now) has silently got broken.

Would you thus recommend that the line above ("with function "=" ...) be
systematically added to each and every existing generic package using
non-limited parameters ?

Thanks for any advice.

--Herv� BITTEUR

hbitteur@club-internet.fr

------ Example - begin
-----------------------------------------------------------

package Ints is
   type Int is new Integer;
   function "=" (Left, Right : Int) return Boolean;
end Ints;

with Ada.Text_IO;   use Ada.Text_IO;
package body Ints is
   function "=" (Left, Right : Int) return Boolean is
   begin
      Put_Line ("Ints. Function '=' is called");
      return True;  -- On purpose, to recognise the call.
   end "=";
end Ints;

generic
   type Item is private;
   Name : in String;
   with function "=" (L, R : in Item) return Boolean is <>;-- Added Line
!!!!!
package Gen_Test is
   procedure Foo (Left, Right : Item);
end Gen_Test;

with Ada.Text_IO;   use Ada.Text_IO;
package body Gen_Test is
   procedure Foo (Left, Right : Item) is
   begin
      if Left = Right then                   -- Which "=" operation ?
         Put_Line (Name & "Gen_Test. Items are equal");
      else
         Put_Line (Name & "Gen_Test. Items are not equal");
      end if;
   end Foo;
end Gen_Test;

with Ints;           use Ints;
with Gen_Test;
with Ada.Text_IO;    use Ada.Text_IO;
procedure Test is
   package Int_Test is new Gen_Test (Int, "Int. ");
   package Integer_Test is new Gen_Test (Integer, "Integer. ");
   I : Int := 1;
   J : Int := 2;
begin
   if I = J then
      Put_Line ("Test. Ints are equal");
   else
      Put_Line ("Test. Ints are not equal");
   end if;
   Int_Test.Foo (I, J);                         -- Ints."="
   Integer_Test.Foo (Integer(I), Integer(J));   -- Predefined "="
end Test;

------ Example - end
-------------------------------------------------------------

Here are the results using GNAT

a/ without the added line:
Ints. Function '=' is called
Test. Ints are equal
Int. Gen_Test. Items are not equal
Integer. Gen_Test. Items are not equal

b/ with the added line:
Ints. Function '=' is called
Test. Ints are equal
Ints. Function '=' is called
Int. Gen_Test. Items are equal
Integer. Gen_Test. Items are not equal




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-03  0:00 Pb with use of redefined "=" operator Fran�oise & Herv� BITTEUR
  1998-11-04  0:00 ` Mats Weber
@ 1998-11-04  0:00 ` dewarr
  1998-11-04  0:00   ` Tucker Taft
  1998-11-04  0:00 ` Matthew Heaney
  2 siblings, 1 reply; 20+ messages in thread
From: dewarr @ 1998-11-04  0:00 UTC (permalink / raw)


In article <363F62F3.3FF7@club-internet.fr>,
  hbitteur@club-internet.fr wrote:
> I just run in a problem when combining :
> - Ada.Strings.Bounded where '=' operator is redefined,
> - A so far correct generic package (old Ada83 code) importing a private
> (non-limited) type.
>
> The problem is that any instantiation of the generic package will use
> the "predefined" equality operator provided with any non-limited type,
> rather than the specific definition related to Ada.Strings.Bounded.
> Which leads to unexpected results on some occasions.
>
> But what puzzles me is that :
> 1/ No warning is raised by the compiler (how could it be otherwise ?)
> 2/ Correct code (till now) has silently got broken.

No warning is issued because there is nothing wrong with your code.
Your program was correct Ada before the change and it is correct
Ada after the change. The RM quite clearly defines that the
predefined equality relation is the one used. The only thing
broken is your understanding and expectations!

To be fair, this often surprises people, but that is the way
the language is designed (for good reasons).

You should pass in the equality operation explicitly to the
generic if that is what you want.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-04  0:00 ` dewarr
@ 1998-11-04  0:00   ` Tucker Taft
  0 siblings, 0 replies; 20+ messages in thread
From: Tucker Taft @ 1998-11-04  0:00 UTC (permalink / raw)


dewarr@my-dejanews.com wrote:
: In article <363F62F3.3FF7@club-internet.fr>,
:   hbitteur@club-internet.fr wrote:
: > I just run in a problem when combining :
: > - Ada.Strings.Bounded where '=' operator is redefined,
: > - A so far correct generic package (old Ada83 code) importing a private
: > (non-limited) type.
: >
: > The problem is that any instantiation of the generic package will use
: > the "predefined" equality operator provided with any non-limited type,
: > rather than the specific definition related to Ada.Strings.Bounded.
: > Which leads to unexpected results on some occasions.
: >
: > But what puzzles me is that :
: > 1/ No warning is raised by the compiler (how could it be otherwise ?)
: > 2/ Correct code (till now) has silently got broken.

: No warning is issued because there is nothing wrong with your code.
: Your program was correct Ada before the change and it is correct
: Ada after the change. The RM quite clearly defines that the
: predefined equality relation is the one used. The only thing
: broken is your understanding and expectations!

: To be fair, this often surprises people, but that is the way
: the language is designed (for good reasons).

: You should pass in the equality operation explicitly to the
: generic if that is what you want.

I might add that the Ada Rapporteur Group (ARG) is considering a binding
interpretation (binding AI) to the language which would require that all 
non-limited types in language-defined packages (such as Ada.Strings.Bounded) 
have "=" operators that compose properly, and work "right" in a generic as well.

This would eliminate the issue for language-defined types at least.

--
-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Burlington, MA  USA
An AverStar Company




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-03  0:00 Pb with use of redefined "=" operator Fran�oise & Herv� BITTEUR
@ 1998-11-04  0:00 ` Mats Weber
  1998-11-04  0:00   ` Fran�oise & Herv� BITTEUR
  1998-11-04  0:00 ` dewarr
  1998-11-04  0:00 ` Matthew Heaney
  2 siblings, 1 reply; 20+ messages in thread
From: Mats Weber @ 1998-11-04  0:00 UTC (permalink / raw)


"Fran�oise & Herv� BITTEUR" wrote:

> The problem is that any instantiation of the generic package will use
> the "predefined" equality operator provided with any non-limited type,
> rather than the specific definition related to Ada.Strings.Bounded.
> Which leads to unexpected results on some occasions.

Go to www.dejanews.com, and do a power search for "reemergence" in the
newsgroup comp.lang.ada, it's already been discussed at length.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-04  0:00 ` Matthew Heaney
@ 1998-11-04  0:00   ` Mats Weber
  1998-11-05  0:00     ` Matthew Heaney
  0 siblings, 1 reply; 20+ messages in thread
From: Mats Weber @ 1998-11-04  0:00 UTC (permalink / raw)


Matthew Heaney wrote:

> ALWAYS import equality for any non-tagged formal type.  In the data
> structure library I'm building, every private type is imported as
> 
> generic
> 
>    type Item_Type is private;
> 
>    with function "="
>      (L, R : Item_Type)
>      return Boolean is <>;
> ...
> package ACL.Stacks.Adapters is ...

I would advise against this, because predefined equality will reemerge
in other situations, such as this:

    type Pair is 
       record
          X, Y : Item_Type;
       end record;

"=" (Pair, Pair) will use the predefined equality on Item_Type, so that
you have to write a new "=" function for Pair. This makes it very hard
to check that the code is correct (i.e. every record/array declaration
that contains a generic formal type must have its own redefined "=").

My advice is that you must know about the reemergence problem and never
instantiate a generic with a type whose predefined "=" does not work.
You can often do this it using tagged types.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-03  0:00 Pb with use of redefined "=" operator Fran�oise & Herv� BITTEUR
  1998-11-04  0:00 ` Mats Weber
  1998-11-04  0:00 ` dewarr
@ 1998-11-04  0:00 ` Matthew Heaney
  1998-11-04  0:00   ` Mats Weber
  2 siblings, 1 reply; 20+ messages in thread
From: Matthew Heaney @ 1998-11-04  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

Fran�oise & Herv� BITTEUR <hbitteur@club-internet.fr> writes:

> I just run in a problem when combining :
> - Ada.Strings.Bounded where '=' operator is redefined,
> - A so far correct generic package (old Ada83 code) importing a private
> (non-limited) type.
> 
> The problem is that any instantiation of the generic package will use
> the "predefined" equality operator provided with any non-limited type,
> rather than the specific definition related to Ada.Strings.Bounded.
> Which leads to unexpected results on some occasions.

This phenonmenon is called "reemergence of predefined operators," and
it's one of Ada's trap doors.  When you import a (non-tagged) type as a
formal type, without also explicitly importing operators, then the
predefined operators for the type are used, irrespective of whether the
actual type has redefined them.


> I have attached a very simplified example to illustrate the situation.
> An obvious fix is to modify the spec of the generic package to
> explicitly import a definition of '=' :
>    with function "=" (L, R : in Item) return Boolean is <>;
> And the redefined version if any (or the predefined one if none) will
> then be used.


ALWAYS import equality for any non-tagged formal type.  In the data
structure library I'm building, every private type is imported as

generic

   type Item_Type is private;

   with function "="
     (L, R : Item_Type)
     return Boolean is <>;
...
package ACL.Stacks.Adapters is ...


> But what puzzles me is that :
> 1/ No warning is raised by the compiler (how could it be otherwise ?)

Unfortunately, this is a "feature" of the language, not a flaw.

> Would you thus recommend that the line above ("with function "=" ...) be
> systematically added to each and every existing generic package using
> non-limited parameters ?

Yes.  Always.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-04  0:00 ` Mats Weber
@ 1998-11-04  0:00   ` Fran�oise & Herv� BITTEUR
  0 siblings, 0 replies; 20+ messages in thread
From: Fran�oise & Herv� BITTEUR @ 1998-11-04  0:00 UTC (permalink / raw)


Mats Weber wrote:
> 
> Go to www.dejanews.com, and do a power search for "reemergence" in the
> newsgroup comp.lang.ada, it's already been discussed at length.

Thanks to all who replied. And especially to Mats Weber for his
practical advice. Since yesterday I've read some 20+ messages on
'dejanews' related to the topic.

Bye.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-04  0:00   ` Mats Weber
@ 1998-11-05  0:00     ` Matthew Heaney
  1998-11-05  0:00       ` Mats Weber
  1998-11-05  0:00       ` dewarr
  0 siblings, 2 replies; 20+ messages in thread
From: Matthew Heaney @ 1998-11-05  0:00 UTC (permalink / raw)


Mats Weber <Mats.Weber@elca-matrix.ch> writes:

> Matthew Heaney wrote:
> 
> > ALWAYS import equality for any non-tagged formal type.  In the data
> > structure library I'm building, every private type is imported as

[snip]
 
> I would advise against this, because predefined equality will reemerge
> in other situations, such as this:
> 
>     type Pair is 
>        record
>           X, Y : Item_Type;
>        end record;
> 
> "=" (Pair, Pair) will use the predefined equality on Item_Type, so that
> you have to write a new "=" function for Pair. This makes it very hard
> to check that the code is correct (i.e. every record/array declaration
> that contains a generic formal type must have its own redefined "=").
> 
> My advice is that you must know about the reemergence problem and never
> instantiate a generic with a type whose predefined "=" does not work.
> You can often do this it using tagged types.

I make it a point that when I create a composite type --an abstract data
type, or "open," as in your example-- that I guarantee equality will
compose.

It is for this reason that I always implement (the full view of) ADTs as
tagged, even if the partial view is not itself tagged.

Mats is correct in pointing out that even if you do import the equality
operator, and you use the imported type as the component of an internal
composite type, that the predefined equality STILL reemerges.

But the solution is trivial: just don't use equality for the composite
type!  What I do is, always declare the equality for composite types as
abstract:

generic
   type Item_Type is private;

   with function "=" (L, R : Item_Type) return Boolean is <>;

package Stacks is 
...
private

   type Pair is
      record
         X, Y : Item_Type;
      end record;

  function "=" 
    (L, R : Pair) return Boolean is abstract;


This way, I won't forget that predefined equality reemerges in Pair, nor
will the unwary maintenance programmer forget either (because the
compiler will tell him when he does forget).

For example, for bounded stack implemented as an array, I do something
like:

private

   type Item_Array is array (Positive range <>) of Item_Type;

   function "=" (L, R : Item_Array) return Boolean is abstract;

   type Stack_Type is
     tagged record
         Items : Item_Array;
         Top : Natural := 0;
      end record;

end Stacks;

package body Stacks is

   function "=" (L, R : Stack_Type) return Boolean is
   begin
      if L.Top = R.Top then
         return False;
      end if;

      for I in 1 .. L.Top loop
         if L.Items (I) /= R.Items (I) then
            return False;
         end if;
      end loop;

      return True;
   end "=";

...


This stack equality operator works, because the equality operator for
the item array type is NOT used (and can't be, because it doesn't
exist).  The imported equality op for Item_Type is used, and thus
equality for the stack type composes.

So my advice _is_ to freely instantiate generics with your equality
operation --even if it doesn't compose-- because the generic should be
written so that it ONLY uses the equality op passed in.  There is no
problem with this approach, and the client does not have to implement
the generic actual type as tagged.





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-05  0:00     ` Matthew Heaney
  1998-11-05  0:00       ` Mats Weber
@ 1998-11-05  0:00       ` dewarr
  1998-11-05  0:00         ` Matthew Heaney
  1 sibling, 1 reply; 20+ messages in thread
From: dewarr @ 1998-11-05  0:00 UTC (permalink / raw)


In article <m3iugv70ke.fsf@mheaney.ni.net>,
  Matthew Heaney <matthew_heaney@acm.org> wrote:


> It is for this reason that I always implement (the full view of) ADTs as
> tagged, even if the partial view is not itself tagged.


I think that this is definitely a wrong approach. The fact of the matter is
that when you get to complex record types, it is rather rare to use the
equality operator meaning just component equality. It seems quite unnecessary
to introduce the overhead resulting from gratuitous tagging just in case this
(mis)use occurs.

In practice I think that the problem is way overblown. Yes, it does cause
some troubles, as we see from yet another thread started up on the subject,
for those who don't know the language rules, but lots of things cause trouble
if you don't know what you are doing!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-05  0:00     ` Matthew Heaney
@ 1998-11-05  0:00       ` Mats Weber
  1998-11-05  0:00         ` Matthew Heaney
  1998-11-05  0:00       ` dewarr
  1 sibling, 1 reply; 20+ messages in thread
From: Mats Weber @ 1998-11-05  0:00 UTC (permalink / raw)


Matthew Heaney wrote:

> I make it a point that when I create a composite type --an abstract data
> type, or "open," as in your example-- that I guarantee equality will
> compose.
> 
> It is for this reason that I always implement (the full view of) ADTs as
> tagged, even if the partial view is not itself tagged.

But if you do that, then you don't need to explicitly import "=" as a
generic formal, because the reemergence problem does not exist with
(visibly or not) tagged types.

This also makes the following trick unnecessary:

> But the solution is trivial: just don't use equality for the composite
> type!  What I do is, always declare the equality for composite types as
> abstract:
> 
> [...]
>    type Pair is
>       record
>          X, Y : Item_Type;
>       end record;
> 
>   function "="
>     (L, R : Pair) return Boolean is abstract;




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-05  0:00       ` dewarr
@ 1998-11-05  0:00         ` Matthew Heaney
  1998-11-06  0:00           ` dewarr
  0 siblings, 1 reply; 20+ messages in thread
From: Matthew Heaney @ 1998-11-05  0:00 UTC (permalink / raw)


dewarr@my-dejanews.com writes:

> In article <m3iugv70ke.fsf@mheaney.ni.net>,
>   Matthew Heaney <matthew_heaney@acm.org> wrote:
> 
> > It is for this reason that I always implement (the full view of) ADTs as
> > tagged, even if the partial view is not itself tagged.
> 
> 
> I think that this is definitely a wrong approach. The fact of the matter is
> that when you get to complex record types, it is rather rare to use the
> equality operator meaning just component equality. It seems quite unnecessary
> to introduce the overhead resulting from gratuitous tagging just in case this
> (mis)use occurs.

So you don't like this implementation of a stack?

   type Stack_Type is private;

private
...
   type Stack_Type is
      tagged record
         Items : Item_Array;
         Top   : Natural := 0;
      end record;


The tagging here hardly seems gratuitous, as it's necessary to correct
what is arguably a flaw in the language!

> In practice I think that the problem is way overblown. Yes, it does cause
> some troubles, as we see from yet another thread started up on the subject,
> for those who don't know the language rules, but lots of things cause trouble
> if you don't know what you are doing!

I don't think this is an accurate comparison.

It is pure fantasy to think that every programmer is going to remember
the somewhat abstruse rules for what operators apply to a type when used
as a generic actual type.

The simplest approach is: 

o write your ADTs so that equality always composes

o when importing a type as a generic formal, use only the equality
operator passed in, and not aggregate comparison

This way the code always works, and no one has to think - which is the
entire point of abstraction!













^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-05  0:00       ` Mats Weber
@ 1998-11-05  0:00         ` Matthew Heaney
  1998-11-09  0:00           ` Robert A Duff
  0 siblings, 1 reply; 20+ messages in thread
From: Matthew Heaney @ 1998-11-05  0:00 UTC (permalink / raw)


Mats Weber <Mats.Weber@elca-matrix.ch> writes:

> Matthew Heaney wrote:
> 
> > I make it a point that when I create a composite type --an abstract data
> > type, or "open," as in your example-- that I guarantee equality will
> > compose.
> > 
> > It is for this reason that I always implement (the full view of) ADTs as
> > tagged, even if the partial view is not itself tagged.
> 
> But if you do that, then you don't need to explicitly import "=" as a
> generic formal, because the reemergence problem does not exist with
> (visibly or not) tagged types.

But not everyone is enlightened as I am :), and they may "forget" to
implement their abstraction as tagged, if they've also overridden
predefined equality.

My philosophy is, I'll make the generic work, so you the client don't
have to think about it.  Bullet-proof abstractions.


> This also makes the following trick unnecessary:
>
> > But the solution is trivial: just don't use equality for the composite
> > type!  What I do is, always declare the equality for composite types as
> > abstract:

This is not a trick: it's a feature of the language!  And besides, this
"trick" is only done inside the generic that imports equality for the
formal type.

Why would anyone complain about using a component that always works?

We are not philosophers debating morality -- we are systems builders.
Our goal is to build correct systems, by whatever means necessary.

If using a language feature to make an abstraction work is "gratuitous,"
or seems like a "trick," then that is a telling observation of the
language itself!





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-05  0:00         ` Matthew Heaney
@ 1998-11-06  0:00           ` dewarr
  1998-11-09  0:00             ` Robert A Duff
  0 siblings, 1 reply; 20+ messages in thread
From: dewarr @ 1998-11-06  0:00 UTC (permalink / raw)


In article <m3lnlq4fqd.fsf@mheaney.ni.net>,
  Matthew Heaney <matthew_heaney@acm.org> wrote:
> dewarr@my-dejanews.com writes:
>
> > In article <m3iugv70ke.fsf@mheaney.ni.net>,
> >   Matthew Heaney <matthew_heaney@acm.org> wrote:
> >
> > > It is for this reason that I always implement (the full view of) ADTs as
> > > tagged, even if the partial view is not itself tagged.
> >
> >
> > I think that this is definitely a wrong approach. The fact of the matter is
> > that when you get to complex record types, it is rather rare to use the
> > equality operator meaning just component equality. It seems quite
unnecessary
> > to introduce the overhead resulting from gratuitous tagging just in case
this
> > (mis)use occurs.
>
> So you don't like this implementation of a stack?
>
>    type Stack_Type is private;
>
> private
> ...
>    type Stack_Type is
>       tagged record
>          Items : Item_Array;
>          Top   : Natural := 0;
>       end record;
>
> The tagging here hardly seems gratuitous, as it's necessary to correct
> what is arguably a flaw in the language!

Right, I think that is a poor implementation of stacks, since it results in
unnecessary inefficiencies, and the utility of being able to compare stacks is
marginal in typical use.

There is of course the currently fashionable code-bloat style of programming
where no one cares if their programs run slowly and take up too much memory,
but the trouble is that if you write standard packages in this style, it very
much restricts the uses they can be put to (in many embedded and safety
critical applications, tagged types are eliminated for good reasons!)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-06  0:00           ` dewarr
@ 1998-11-09  0:00             ` Robert A Duff
  1998-11-10  0:00               ` dennison
  0 siblings, 1 reply; 20+ messages in thread
From: Robert A Duff @ 1998-11-09  0:00 UTC (permalink / raw)


dewarr@my-dejanews.com writes:

> There is of course the currently fashionable code-bloat style of programming
> where no one cares if their programs run slowly and take up too much memory,
> but the trouble is that if you write standard packages in this style, it very
> much restricts the uses they can be put to...

I very much agree with the above (I hate buying new hardware that's 2
times faster, and then finding that it's only 1.1 times faster in
practise because the new software that goes with it makes up for the
speed gains), but:

>...(in many embedded and safety
> critical applications, tagged types are eliminated for good reasons!)

I disagree with that part.  Making a type tagged adds one word of
storage to each object of the type, in typical implementations of Ada.
It's quite easy to decide on a case-by-case basis whether that's "too
much".

There might be reasons to forbid the 'Class attribute in certain
safety-critical applications, but I see no reason to forbid "tagged".
Tagged types (without 'Class) don't introduce any dynamic dispatching or
anything else that might be of concern.

I've heard some safety-critical folks talking about not using "tagged"
because it introduces dynamic dispatching.  But that's a
misunderstanding of the language -- if you want to prevent dynamic
dispatching, then forbid 'Class.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-05  0:00         ` Matthew Heaney
@ 1998-11-09  0:00           ` Robert A Duff
  1998-11-09  0:00             ` Brian Rogoff
  1998-11-10  0:00             ` Robert I. Eachus
  0 siblings, 2 replies; 20+ messages in thread
From: Robert A Duff @ 1998-11-09  0:00 UTC (permalink / raw)


Matthew Heaney <matthew_heaney@acm.org> writes:

> Why would anyone complain about using a component that always works?

Because it's too slow?

Maybe it's no big deal for your stack example -- maybe the stack needs
100 words, and the tag field makes it 101.  But suppose the abstraction
were "point-in-a-plane" or "complex", where the thing needs two words of
useful data -- in that case, adding a tag field is a huge space
inefficiency.  And don't tell me memory is cheap -- it takes time to
initialize it, and it can wreck your caching behavior, which costs time,
and time is *not* cheap.

> We are not philosophers debating morality -- we are systems builders.
> Our goal is to build correct systems, by whatever means necessary.
> 
> If using a language feature to make an abstraction work is "gratuitous,"
> or seems like a "trick," then that is a telling observation of the
> language itself!

Yes, the language has a flaw.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-09  0:00           ` Robert A Duff
@ 1998-11-09  0:00             ` Brian Rogoff
  1998-11-10  0:00               ` Robert A Duff
  1998-11-10  0:00             ` Robert I. Eachus
  1 sibling, 1 reply; 20+ messages in thread
From: Brian Rogoff @ 1998-11-09  0:00 UTC (permalink / raw)


On Mon, 9 Nov 1998, Robert A Duff wrote:

> Matthew Heaney <matthew_heaney@acm.org> writes:
> 
> > Why would anyone complain about using a component that always works?
> 
> Because it's too slow?
> 
> Maybe it's no big deal for your stack example -- maybe the stack needs
> 100 words, and the tag field makes it 101.  But suppose the abstraction
> were "point-in-a-plane" or "complex", where the thing needs two words of
> useful data -- in that case, adding a tag field is a huge space
> inefficiency.  And don't tell me memory is cheap -- it takes time to
> initialize it, and it can wreck your caching behavior, which costs time,
> and time is *not* cheap.

I agree that certain "small" data types are best not tagged, but I would
think that a collection in general is not such a type. Indeed, we have to
use tagged types for collections if we want the ability to treat them as 
values and define our own ":=". I'm definitely struggling with some of the 
same issues that Matt is struggling with, in my own attempts to create a 
flexible, usable, and most of all, efficient, data structure library. I
haven't found any totally satisfactory approaches.

I really liked the way that Sather divided its types into immutable (stack
allocated) value types and mutable (heap allocated) reference types, and
how it also used $ for the polymorphic abstract types. Too bad its a dead 
language. In any case, its lack of a proper module system was really a 
pain.

> > If using a language feature to make an abstraction work is "gratuitous,"
> > or seems like a "trick," then that is a telling observation of the
> > language itself!
> 
> Yes, the language has a flaw.

Unfortunately, it has many, many flaws. The real pity is that I don't
think that there are really any better languages out there in the same
language design space. Maybe one day someone will design a successor to 
Ada unencumbered by backwards compatibility (*).  

-- Brian

(*) No, Eiffel isn't even close, IMO.






^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-09  0:00             ` Robert A Duff
@ 1998-11-10  0:00               ` dennison
  1998-11-10  0:00                 ` Robert A Duff
  0 siblings, 1 reply; 20+ messages in thread
From: dennison @ 1998-11-10  0:00 UTC (permalink / raw)


In article <wcchfw8sfg2.fsf@world.std.com>,
  Robert A Duff <bobduff@world.std.com> wrote:
> dewarr@my-dejanews.com writes:
>
> >...(in many embedded and safety
> > critical applications, tagged types are eliminated for good reasons!)
>
> I disagree with that part.  Making a type tagged adds one word of
> storage to each object of the type, in typical implementations of Ada.
> It's quite easy to decide on a case-by-case basis whether that's "too
> much".
>
> There might be reasons to forbid the 'Class attribute in certain
> safety-critical applications, but I see no reason to forbid "tagged".
> Tagged types (without 'Class) don't introduce any dynamic dispatching or
> anything else that might be of concern.

My understanding was that without 'Class, the tag may not even be *present*
in the object. It isn't really needed, since every object's type is
determinable at compile time.

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-10  0:00               ` dennison
@ 1998-11-10  0:00                 ` Robert A Duff
  0 siblings, 0 replies; 20+ messages in thread
From: Robert A Duff @ 1998-11-10  0:00 UTC (permalink / raw)


dennison@telepath.com writes:

> My understanding was that without 'Class, the tag may not even be *present*
> in the object. It isn't really needed, since every object's type is
> determinable at compile time.

But when the compiler lays out objects of the type it needs to decide
whether to include a tag field.  It doesn't know if some other part of
the program will mention 'Class (unless it has global knowledge, eg by
deferring all code generation to link time).

Consider:

    package P is
        type T1 is tagged null record;
        X: T1;
        procedure Do_Something(X: T1);
        procedure Do_Something_Else(X: T1);
    end P;

    with P; use P;
    package Q is
        type T2 is new T1 with null record;
        Y: T2;
        procedure Do_Something_Else(X: T2);
    end Q;

    with P; use P;
    with Q; use Q;
    procedure Main is
    begin
        Do_Something(P.X);
        Do_Something(Q.Y);
    end Main;

    package body P is
        procedure Do_Something(X: T1) is
	begin
	    Do_Something_Else(T1'Class(X)); <<--------------------
	end Do_Something;

        procedure Do_Something_Else(X: T1) is
        begin
            ...
        end Do_Something_Else;
    end P;

In the usual implementation model, both variables X and Y need a tag
field, but we haven't yet seen any 'Class when they are compiled.  An
alternative is to store tags with parameters and pointers, instead of
with the objects themselves.  I don't know of any compilers that do
that, and I'm not sure it's a good idea -- it seems kind of annoying to
double the size of all access-to-classwide types.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-09  0:00             ` Brian Rogoff
@ 1998-11-10  0:00               ` Robert A Duff
  0 siblings, 0 replies; 20+ messages in thread
From: Robert A Duff @ 1998-11-10  0:00 UTC (permalink / raw)


Brian Rogoff <bpr@shell5.ba.best.com> writes:

> I agree that certain "small" data types are best not tagged, but I would
> think that a collection in general is not such a type.  ...

I'm not so sure.  Suppose you give me a package that implements a
reusable "list of things" type.  And suppose I'm writing a compiler, and
I want to use that type to represent the parameter lists of function
calls in the parse tree.  Well, I need to be able to deal with fairly
long lists, and write all my algorithms to deal with any length, but I
suspect the *average* list length in this case would be about 1.2 items
(just my guess!).  So adding an extra word of storage for a bogus tag
field is a lot, if I don't need it.  So in that case, I don't want to
use the "reusable" code.

> Unfortunately, it has many, many flaws.

Indeed.  They all do.  But this field is still pretty young.

>... The real pity is that I don't
> think that there are really any better languages out there in the same
> language design space. Maybe one day someone will design a successor to 
> Ada unencumbered by backwards compatibility (*).  

Backwards compatibility was indeed the most difficult design constraint
on Ada 9X.  I've heard similar comments from Stroustrup about C and C++.

But backwards compatibility is what everybody wants.  Even Java has a
form of backwards compatibility -- it sort of looks like C, on the
surface.

> (*) No, Eiffel isn't even close, IMO.

But it has some good ideas in it, too.

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Pb with use of redefined "=" operator
  1998-11-09  0:00           ` Robert A Duff
  1998-11-09  0:00             ` Brian Rogoff
@ 1998-11-10  0:00             ` Robert I. Eachus
  1 sibling, 0 replies; 20+ messages in thread
From: Robert I. Eachus @ 1998-11-10  0:00 UTC (permalink / raw)


In article <wccg1bssf6n.fsf@world.std.com> Robert A Duff <bobduff@world.std.com> writes:

 > Maybe it's no big deal for your stack example -- maybe the stack needs
 > 100 words, and the tag field makes it 101.  But suppose the abstraction
 > were "point-in-a-plane" or "complex", where the thing needs two words of
 > useful data -- in that case, adding a tag field is a huge space
 > inefficiency.  And don't tell me memory is cheap -- it takes time to
 > initialize it, and it can wreck your caching behavior, which costs time,
 > and time is *not* cheap.

 > Yes, the language has a flaw.

   If the langauge has a flaw, let's be certain that we know what that
flaw is.  As I see it, the fact that all objects of tagged types must
have an explicit tag is a side effect of the rule that all objects of
tagged types are aliased 3.10(9).  But that rule DOES NOT require that
all tagged subcomponents must be aliased.  In particular, you could
have an array of some tagged type:

   Running the attached program through gnat produces the expected
error messages. (Actually you need to run it twice, once with the
object declarations commented out.)  The key message is:

ttest.ads:31:28: prefix of "access" attribute must be aliased

   So as far as I can tell, requiring 40 bits for the type
Tagged_Object is a (legitimate) implementation restriction for gnat,
not a language requirement. Tagged subcomponents of array or record
types need not have individual tags, but implementors have not tried
to fiercely pack such types.  This is probably due to 6.2(4,5,and 10).
If you pass an element of Tagged_Array as a parameter, it must be
passed by-reference.  There is no theoretical problem with always
passing the tag as a separate parameter, since assignment to an object
or component can never change the tag.  But that would require a
substantial amount of work--and make all calls with tagged parameters
slower.  Some Ada compilers have done the equivalent for array
parameters, so it is not out of the question.  But I would hope that
any Ada compiler that supported the capability would require that the
(component) tagged type be the subject of a representation
pragma. (Separable_Tag maybe?)

   (If Bob Duff really was worried about the requirement that a tagged
complex object must have a one word tag, well yes, that is required,
but I refuse to worry about one word of storage.)

------------------------------------------------------------------------

package ttest is

    type Tagged_Object is tagged record
      X: Boolean := True;
    end record;

    for Tagged_Object'Size use 8;

    type Small_Object is record
      X: Boolean := True;
    end record;

    type Tagged_Array is array (Integer range 1..1000) of Tagged_Object;
    pragma Pack(Tagged_Array);
    for Tagged_Array'Size use 1000;

    type Small_Array is array (Integer range 1..1000) of Small_Object;
    pragma Pack(Small_Array);
    for Small_Array'Size use 1000;

    type Smaller_Array is array(1..1000) of Boolean;
    pragma Pack(Smaller_Array);
    for Smaller_Array'Size use 1000;

    type Smallest_Array is array(1..32) of Boolean;
    pragma Pack(Smallest_Array);
    for Smallest_Array'Size use 32;

    type Tagged_Access is access all Tagged_Object;

    TArr: Tagged_Array;

    TAcc: Tagged_Access := TArr(2)'Access;

end ttest;
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~1998-11-10  0:00 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-11-03  0:00 Pb with use of redefined "=" operator Fran�oise & Herv� BITTEUR
1998-11-04  0:00 ` Mats Weber
1998-11-04  0:00   ` Fran�oise & Herv� BITTEUR
1998-11-04  0:00 ` dewarr
1998-11-04  0:00   ` Tucker Taft
1998-11-04  0:00 ` Matthew Heaney
1998-11-04  0:00   ` Mats Weber
1998-11-05  0:00     ` Matthew Heaney
1998-11-05  0:00       ` Mats Weber
1998-11-05  0:00         ` Matthew Heaney
1998-11-09  0:00           ` Robert A Duff
1998-11-09  0:00             ` Brian Rogoff
1998-11-10  0:00               ` Robert A Duff
1998-11-10  0:00             ` Robert I. Eachus
1998-11-05  0:00       ` dewarr
1998-11-05  0:00         ` Matthew Heaney
1998-11-06  0:00           ` dewarr
1998-11-09  0:00             ` Robert A Duff
1998-11-10  0:00               ` dennison
1998-11-10  0:00                 ` Robert A Duff

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