comp.lang.ada
 help / color / mirror / Atom feed
* Re: Array of Variant Records Question...
  1999-09-08  0:00 Array of Variant Records Question Bruce Detter
                   ` (2 preceding siblings ...)
  1999-09-08  0:00 ` Matthew Heaney
@ 1999-09-08  0:00 ` Ted Dennison
  3 siblings, 0 replies; 69+ messages in thread
From: Ted Dennison @ 1999-09-08  0:00 UTC (permalink / raw)


In article <7r5vh3$imu1@svlss.lmms.lmco.com>,
  "Bruce Detter" <bruce.detter@lmco.com> wrote:
> How do you declare an array of variant records where each variant
record's
> descriminant is the array index?  Can it be done at all?  I would
prefer not
> to use access pointers if it can be avoided.

I don't really see a way to do that. I think you'd have to load those
values into the record discrimintants manually. If the record type has a
default value for the discriminant you could use a loop to do it.
Otherwise you will have to load each discriminant value in literally in
an initialization when the object is declared. Alternatively you could
try creating an (impure) function that returns the first index the first
time its called, and a number 1 higher each subsequent time. Then you
could use that function to initialize the discriminant fields in the
records when they are declared.

Out of curiosity, what are you trying to accomplish with this? The
typical use for a numerical discriminant in a variant record is to size
an array subfield of that record. What you are asking for would then
give you a sort of triangular matrix; an interesting structure indeed.

--
T.E.D.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-08  0:00 Array of Variant Records Question Bruce Detter
  1999-09-08  0:00 ` Thank you Bruce Detter
@ 1999-09-08  0:00 ` Martin C. Carlisle
  1999-09-08  0:00 ` Matthew Heaney
  1999-09-08  0:00 ` Ted Dennison
  3 siblings, 0 replies; 69+ messages in thread
From: Martin C. Carlisle @ 1999-09-08  0:00 UTC (permalink / raw)


In article <7r5vh3$imu1@svlss.lmms.lmco.com>,
Bruce Detter <bruce.detter@lmco.com> wrote:
>How do you declare an array of variant records where each variant record's
>descriminant is the array index?  Can it be done at all?  I would prefer not
>to use access pointers if it can be avoided.

If this is all you need, why not just make regular records, where a field
is the array index?

--Martin

-- 
Martin C. Carlisle, Asst Prof of Computer Science, US Air Force Academy
carlislem@acm.org, http://www.usafa.af.mil/dfcs/bios/carlisle.html
DISCLAIMER:  This content in no way reflects the opinions, standards or 
policy of the US Air Force Academy or the United States Government.




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

* Re: Array of Variant Records Question...
  1999-09-08  0:00 Array of Variant Records Question Bruce Detter
  1999-09-08  0:00 ` Thank you Bruce Detter
  1999-09-08  0:00 ` Array of Variant Records Question Martin C. Carlisle
@ 1999-09-08  0:00 ` Matthew Heaney
  1999-09-08  0:00   ` Mike Silva
  1999-09-08  0:00 ` Ted Dennison
  3 siblings, 1 reply; 69+ messages in thread
From: Matthew Heaney @ 1999-09-08  0:00 UTC (permalink / raw)


In article <7r5vh3$imu1@svlss.lmms.lmco.com> , "Bruce Detter" 
<bruce.detter@lmco.com> wrote:

> How do you declare an array of variant records where each variant record's
> descriminant is the array index?  Can it be done at all?  I would prefer not
> to use access pointers if it can be avoided.

I did something like this in all my dining philosopher examples, in the ACM
Ada95 design pattern archives.  Look for the "Dining Philosophers" example
in the Apr 99 link.

In that example, it's a task that has a discriminant, but that's equivalent
to your variant record.


   subtype Philosopher_Id is Positive range 1 .. 5;

   package Id_Management is

      function Get_Id return Philosopher_Id;

   end;
   use Id_Management;

   package body Id_Management is

      Id : Natural := 0;

      function Get_Id return Philosopher_Id is
      begin
         Id := Id + 1;
         return Id;
      end;

   end Id_Management;



   task type Philosopher_Task_Type
     (Id : Philosopher_Id := Get_Id) is

      entry Start;
   end;

   type Philosopher_Task_Array is
      array (Philosopher_Id) of Philosopher_Task_Type;

   Philosopher_Tasks : Philosopher_Task_Array;


At elaboration time, as each task in the array elaborates, it calls Get_Id,
which returns an Id for that task.

Note, however, that there is no necessary correlation between the order of
elaboration of array elements, and the index of the array.  In the example
I've shown above, the task Philosopher_Tasks (1) doesn't necessarily have an
Id with the value 1.

If you need that correspondence, you're going to have to use indirection.
Populate another array with access objects designating the task with that
array index, ie

   <as before>

   type Philosopher_Task_Array is
      array (Philosopher_Id) of aliased Philosopher_Task_Type;
   -- array components are now aliased

   Philosopher_Tasks : Philosopher_Task_Array;

   type Philosopher_Task_Access is
     access all Philosopher_Task_Type;

   type Philosopher_Task_Access_Array is
     array (Philosopher_Id) of Philosopher_Task_Access;

   Philosopher_Index : Philosopher_Task_Access_Array;
   ...
 begin  -- the begin part of the body, or where-ever

   for Id in Philosopher_Tasks'Range loop
     declare
       PT : Philosopher_Task_Type renames
          Philosopher_Task_Array (Id);
     begin
       Philosopher_Index (PT.Id) := PT'Access;
     end;
   end loop;

  end;


Now Philosopher_Index (i) points to the philosopher task whose Id = i.  So
you'll have to use a level of indirection:

  declare
    PT : Phil_Task_Type renames Philosopher_Index (I).all;
  begin
    -- PT.Id = I


Sorry it's a bit complicated; this is one of the glaring flaws in the
language.  But as you can see there is a work-around.

--
Matt

It is impossible to feel great confidence in a negative theory which has
always rested its main support on the weak points of its opponent.

Joseph Needham, "A Mechanistic Criticism of Vitalism"




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

* Re: Array of Variant Records Question...
  1999-09-08  0:00 ` Matthew Heaney
@ 1999-09-08  0:00   ` Mike Silva
  1999-09-08  0:00     ` Matthew Heaney
  1999-09-09  0:00     ` Array of Variant Records Question Nick Roberts
  0 siblings, 2 replies; 69+ messages in thread
From: Mike Silva @ 1999-09-08  0:00 UTC (permalink / raw)


I didn't get it -- what is the flaw?  What would be the "proper" solution to
remove the flaw?

Mike

Matthew Heaney wrote in message <37d6a45c@news1.prserv.net>...

>Sorry it's a bit complicated; this is one of the glaring flaws in the
>language.  But as you can see there is a work-around.







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

* Thank you
  1999-09-08  0:00 Array of Variant Records Question Bruce Detter
@ 1999-09-08  0:00 ` Bruce Detter
  1999-09-08  0:00   ` Martin C. Carlisle
  1999-09-08  0:00 ` Array of Variant Records Question Martin C. Carlisle
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 69+ messages in thread
From: Bruce Detter @ 1999-09-08  0:00 UTC (permalink / raw)



Bruce Detter <bruce.detter@lmco.com> wrote in message
news:7r5vh3$imu1@svlss.lmms.lmco.com...
> How do you declare an array of variant records where each variant record's
> descriminant is the array index?  Can it be done at all?  I would prefer
not
> to use access pointers if it can be avoided.
>
> --
> Bruce C. Detter III
>
>
Thank you for your response, a little experimentation based on Mr. Heaney's
solution provided the answer.  I used a default variant for the array type
declaration, and "re-initialized" the array elements to what I wanted when
the array was instanciated.

Professor Carlisle, I have several "message" structures I receive, each with
1 or more states I need to represent with ascii characters.  I wanted to
have a single place where I could look up the ascii characters up based on
the message type and state.  There is probably several ways I could have
done this including wrapping the message structure with in a tagged record
and using polymorphism,  but I choose the down and dirty, brute force method
(for the time being)

BCD3






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

* Re: Thank you
  1999-09-08  0:00 ` Thank you Bruce Detter
@ 1999-09-08  0:00   ` Martin C. Carlisle
  0 siblings, 0 replies; 69+ messages in thread
From: Martin C. Carlisle @ 1999-09-08  0:00 UTC (permalink / raw)


It sounds like you did something like the following:
with ada.integer_text_io;
with ada.text_io;
procedure test_discrim is
  type bob(discrim : integer := 1) is record
     dummy : integer;
  end record;
  
  type fred is array(integer range <>) of bob;
  x : fred(1..10);
begin
  for i in x'range loop
     x(i) := bob'(discrim => i, dummy => 0);
  end loop;
  
  for i in x'range loop
     ada.integer_text_io.put(x(i).discrim);
     ada.text_io.new_line;
  end loop;
end test_discrim;

But, I still don't see why discrim can't just be a field of the 
record.  (I guess you do have the advantage that discrim can't
be modified w/o reassigning the entire record.)

--Martin

In article <7r6acf$imu3@svlss.lmms.lmco.com>,
Bruce Detter <bruce.detter@lmco.com> wrote:
>
>Bruce Detter <bruce.detter@lmco.com> wrote in message
>news:7r5vh3$imu1@svlss.lmms.lmco.com...
>> How do you declare an array of variant records where each variant record's
>> descriminant is the array index?  Can it be done at all?  I would prefer
>not
>> to use access pointers if it can be avoided.
>Thank you for your response, a little experimentation based on Mr. Heaney's
>solution provided the answer.  I used a default variant for the array type
>declaration, and "re-initialized" the array elements to what I wanted when
>the array was instanciated.
>
>Professor Carlisle, I have several "message" structures I receive, each with
>1 or more states I need to represent with ascii characters.  I wanted to
>have a single place where I could look up the ascii characters up based on
>the message type and state.  There is probably several ways I could have
>done this including wrapping the message structure with in a tagged record
>and using polymorphism,  but I choose the down and dirty, brute force method
>(for the time being)
-- 
Martin C. Carlisle, Asst Prof of Computer Science, US Air Force Academy
carlislem@acm.org, http://www.usafa.af.mil/dfcs/bios/carlisle.html
DISCLAIMER:  This content in no way reflects the opinions, standards or 
policy of the US Air Force Academy or the United States Government.




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

* Re: Array of Variant Records Question...
  1999-09-08  0:00   ` Mike Silva
@ 1999-09-08  0:00     ` Matthew Heaney
  1999-09-09  0:00       ` Robert Dewar
  1999-09-09  0:00     ` Array of Variant Records Question Nick Roberts
  1 sibling, 1 reply; 69+ messages in thread
From: Matthew Heaney @ 1999-09-08  0:00 UTC (permalink / raw)


In article <eExB3.6$ZR.1146@news.wenet.net> , "Mike Silva" <mjsilva@jps.net>
wrote:

> I didn't get it -- what is the flaw?  What would be the "proper" solution to
> remove the flaw?

> Mike
>
> Matthew Heaney wrote in message <37d6a45c@news1.prserv.net>...
>
>>Sorry it's a bit complicated; this is one of the glaring flaws in the
>>language.  But as you can see there is a work-around.

To have array initialization a la Fortran, something like:

  type T (Id : Positive := 1) is record ... end record;

  type TA is array (Positive range <>) of T;

  function Init (I : Positive) return T;

  O : TA (1 .. 5) := (for I in O'Range => O (I) := Init (I));

where

  function Init (I : Positive) return T is
    O : TA (I);
  begin
    return O;
  end Init;


This syntax is off the top of my head; there are probably better ways to do
it, that would obviate the need for Init.

The language maintainers also have to settle the issue of invoking
constructors for limited types during the declaration of the object.  One
proposal is to allow constructors (functions returning T) to be called in
the declarative region.






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

* Array of Variant Records Question...
@ 1999-09-08  0:00 Bruce Detter
  1999-09-08  0:00 ` Thank you Bruce Detter
                   ` (3 more replies)
  0 siblings, 4 replies; 69+ messages in thread
From: Bruce Detter @ 1999-09-08  0:00 UTC (permalink / raw)


How do you declare an array of variant records where each variant record's
descriminant is the array index?  Can it be done at all?  I would prefer not
to use access pointers if it can be avoided.

--
Bruce C. Detter III






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

* Re: Array of Variant Records Question...
  1999-09-08  0:00     ` Matthew Heaney
@ 1999-09-09  0:00       ` Robert Dewar
  1999-09-09  0:00         ` Matthew Heaney
  0 siblings, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-09  0:00 UTC (permalink / raw)


In article <37d6ccb6@news1.prserv.net>,
  "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> To have array initialization a la Fortran, something like:
>
>   type T (Id : Positive := 1) is record ... end record;
>
>   type TA is array (Positive range <>) of T;
>
>   function Init (I : Positive) return T;
>
>   O : TA (1 .. 5) := (for I in O'Range => O (I) := Init (I));
> This syntax is off the top of my head; there are probably
better ways to do
> it, that would obviate the need for Init.
>
> The language maintainers also have to settle the issue of
invoking
> constructors for limited types during the declaration of the
object.  One
> proposal is to allow constructors (functions returning T) to
be called in
> the declarative region.


No need to invent syntax, this proposal was part of the language
design at one point, but was removed as being an excessively
complex feature for too little gain. There were even conditional
expressions to use in this context.

Matthew, as someone who is always feature hungry and always
wants more complexity in the language, you should definitely
read mapping document 2, you would probably like all kinds
of bells and whistles you found there :-)


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-08  0:00   ` Mike Silva
  1999-09-08  0:00     ` Matthew Heaney
@ 1999-09-09  0:00     ` Nick Roberts
  1999-09-09  0:00       ` Tucker Taft
  1999-09-09  0:00       ` Robert Dewar
  1 sibling, 2 replies; 69+ messages in thread
From: Nick Roberts @ 1999-09-09  0:00 UTC (permalink / raw)


The flaw is that Ada has no 'polymorphic array type': an array that has an
indefinite component subtype.

As I suggested in a post a few months ago, such an array type would be easy
to add to Ada's existing syntax, easy and efficient to implement (as an
array of pointers plus a ragged sequence of objects, internally), and very
bloody useful, pardon the language. (It would have solved Bruce's problem in
a trice.)

Maybe come the next review...

-------------------------------------
Nick Roberts
http://www.adapower.com/lab/adaos
-------------------------------------

Mike Silva <mjsilva@jps.net> wrote in message
news:eExB3.6$ZR.1146@news.wenet.net...
| I didn't get it -- what is the flaw?  What would be the "proper" solution
to
| remove the flaw?







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

* Re: Array of Variant Records Question...
  1999-09-09  0:00     ` Array of Variant Records Question Nick Roberts
  1999-09-09  0:00       ` Tucker Taft
@ 1999-09-09  0:00       ` Robert Dewar
  1 sibling, 0 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-09  0:00 UTC (permalink / raw)


In article <37d74dea@eeyore.callnetuk.com>,
  "Nick Roberts" <nickroberts@callnetuk.com> wrote:
> As I suggested in a post a few months ago, such an array type
would be easy
> to add to Ada's existing syntax, easy and efficient to
implement (as an
> array of pointers plus a ragged sequence of objects,
internally), and very
> bloody useful, pardon the language. (It would have solved
Bruce's problem in
> a trice.)


Not at *all* easy to implement, the use of implicit pointers
is unacceptable for many reasons, and it is not at all easy
to see how to implement it without the use of implicit pointers.
I think this is NOT something you are likely to see in any
future revision of the language.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00     ` Array of Variant Records Question Nick Roberts
@ 1999-09-09  0:00       ` Tucker Taft
  1999-09-10  0:00         ` Nick Roberts
  1999-09-09  0:00       ` Robert Dewar
  1 sibling, 1 reply; 69+ messages in thread
From: Tucker Taft @ 1999-09-09  0:00 UTC (permalink / raw)


Nick Roberts wrote:
> 
> The flaw is that Ada has no 'polymorphic array type': an array that has an
> indefinite component subtype.
> 
> As I suggested in a post a few months ago, such an array type would be easy
> to add to Ada's existing syntax, easy and efficient to implement (as an
> array of pointers plus a ragged sequence of objects, internally), and very
> bloody useful, pardon the language. (It would have solved Bruce's problem in
> a trice.)

We considered full support for "indefinite"/unconstrained subtypes
during the Ada 9X process, but ultimately decided to avoid any
language feature that would require implicit levels of indirection
within an object.  The general philosophy here is that levels of indirection
should be under the control of the programmer, not the compiler.
You can certainly create a structure much like what you propose by
an array of pointers, initialized with a sequence of allocators.
The benefits from building such a capability into the language
itself would probably not justify the added complexity, particularly
when you consider the fine level of representation control Ada programmers
desire over data structures.

> 
> Maybe come the next review...

If you have a detailed proposal with examples, ACVC tests, etc., feel free
to document it.  However, don't hold your breath for this to happen,
since (at least as far as I understand it) does not seem to be providing
significant new capability that cannot be programmed already using
existing features.
> 
> -------------------------------------
> Nick Roberts
> http://www.adapower.com/lab/adaos
> -------------------------------------
> 
> Mike Silva <mjsilva@jps.net> wrote in message
> news:eExB3.6$ZR.1146@news.wenet.net...
> | I didn't get it -- what is the flaw?  What would be the "proper" solution
> to
> | remove the flaw?

-- 
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00       ` Robert Dewar
@ 1999-09-09  0:00         ` Matthew Heaney
  1999-09-09  0:00           ` Matthew Heaney
  1999-09-09  0:00           ` Robert Dewar
  0 siblings, 2 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-09  0:00 UTC (permalink / raw)


In article <7r77i8$i08$1@nnrp1.deja.com> , Robert Dewar 
<robert_dewar@my-deja.com>  wrote:


> Matthew, as someone who is always feature hungry and always
> wants more complexity in the language, you should definitely
> read mapping document 2, you would probably like all kinds
> of bells and whistles you found there :-)

Fair enough.  Can someone post the URL of the mapping document(s), or tell
me how to get it?  I looked around the AdaIC but didn't find anything.

Thanks,
Matt

P.S.  Here's some more stuff I want:

1) access constant params

2) the ability to cast away const w/o using Sys.Addr_To_Acc_Convs

3) types whose full view is limited should be implicitly aliased, just like
for tagged types

4) implicit conversion of an access param to a named access type

5) implicit conversion of a specific access type to an access type that
designates an ancestor that is class-wide

6) the ability to invoke a constructor/initializer for limited types in the
declarative region

7) downward closures




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00         ` Matthew Heaney
@ 1999-09-09  0:00           ` Matthew Heaney
  1999-09-09  0:00             ` Robert Dewar
  1999-09-09  0:00             ` Mark Lundquist
  1999-09-09  0:00           ` Robert Dewar
  1 sibling, 2 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-09  0:00 UTC (permalink / raw)


In article <37d7c116@news1.prserv.net> , "Matthew Heaney" 
<matthew_heaney@acm.org> wrote:

> P.S.  Here's some more stuff I want:

1) - 7) snipped

I forgot some more stuff:

8) T'Class for types that aren't tagged.

9) Controlled-ness applied to access types directly.

10) For GNAT to implement pragma Restrictions (Max_Task_Entries => 0), so
that it can generate a more efficient RTS.

11) For GNAT to really implement Suspension_Objects, instead of just
implementing them as a protected type.

12) For ACT to port GNAT to LinuxPPC.

13) For me to win US$1_000_000 in the lottery.






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

* Re: Array of Variant Records Question...
  1999-09-09  0:00           ` Matthew Heaney
@ 1999-09-09  0:00             ` Robert Dewar
  1999-09-09  0:00             ` Mark Lundquist
  1 sibling, 0 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-09  0:00 UTC (permalink / raw)


In article <37d7d2ff@news1.prserv.net>,
  "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> 8) T'Class or types that aren't tagged.

Again, a feature in mapping document 2, very controversial,
bit the dust. Basic arguments against this are that

  a) it would cause significant changes in the RM (ho ho,
     that was back in the days when we fooled ourselves
     into thinking this would not happen anyway).

  b) it seemed to open up too big a door in the typing model,
     and that is still a valid objection. However, this is
     definitely a reasonable item to rediscuss.

> 9) Controlled-ness applied to access types directly.

  Shrug, no opinion, seems unimportant to me.

> 10) For GNAT to implement pragma Restrictions
(Max_Task_Entries => 0), so
> that it can generate a more efficient RTS.

  The latest version of GNAT on some targets implements a
  restricted run time that roughly corresponds to the Ravenscar
  model, since this seems to be what people want. There is no
  likelihood of doing JUST the above case, since so far there
  is no demand.

> 11) For GNAT to really implement Suspension_Objects, instead
of just
> implementing them as a protected type.

  Our approach here is to optimize simple protected types.
  SO's as such are not of particular interest to us.

> 12) For ACT to port GNAT to LinuxPPC.

  We have in fact done an experimental version of this port, and
  it is being beta tested now. No commitments for the future
  support of this port have been made, but it is a good guess
  that it will become real sometime in the future.

> 13) For me to win US$1_000_000 in the lottery.

  Sorry, for this you have to be a supported customer :-) :-)
  (a lucky one!)

Robert Dewar
Ada Core Technologies


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00         ` Matthew Heaney
  1999-09-09  0:00           ` Matthew Heaney
@ 1999-09-09  0:00           ` Robert Dewar
  1999-09-09  0:00             ` Matthew Heaney
                               ` (2 more replies)
  1 sibling, 3 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-09  0:00 UTC (permalink / raw)


In article <37d7c116@news1.prserv.net>,
  "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> 1) access constant params

no comment, not exciting ...>

> 2) the ability to cast away const w/o using
Sys.Addr_To_Acc_Convs

Sorry, no idea what this means

> 3) types whose full view is limited should be implicitly
aliased, just like for tagged types

This sounds distinctly NOT upwards compatible since it may
change representations

> 4) implicit conversion of an access param to a named access
type
>
> 5) implicit conversion of a specific access type to an access
type that
> designates an ancestor that is class-wide

Personally I don't like to add any implicit conversions, but
I think there is some sentiment for additions along these lines.

> 6) the ability to invoke a constructor/initializer for limited
types in the
> declarative region

sorry, I do not know what you mean here, and I certainly
do not know what a constructor is, example would be useful.

> 7) downward closures

discussed to death already, not worth discussing further ...


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00           ` Robert Dewar
@ 1999-09-09  0:00             ` Matthew Heaney
  1999-09-10  0:00               ` Robert Dewar
                                 ` (2 more replies)
  1999-09-09  0:00             ` Array of Variant Records Question Brian Rogoff
  1999-09-10  0:00             ` Proposed Ada features (was Re: Array of Variant Records Question...) Mark Lundquist
  2 siblings, 3 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-09  0:00 UTC (permalink / raw)


In article <7r8t21$ov5$1@nnrp1.deja.com> , Robert Dewar 
<robert_dewar@my-deja.com>  wrote:

>> 2) the ability to cast away const w/o using
> Sys.Addr_To_Acc_Convs
>
> Sorry, no idea what this means

To be able to modify an in-mode subprogram parameter.  Essentially, what ACT
did to implement the function Random in GNAT.

(The locution "cast away const" comes from C++.)


>> 6) the ability to invoke a constructor/initializer for limited types in the
>> declarative region
>
> sorry, I do not know what you mean here, and I certainly
> do not know what a constructor is, example would be useful.

In Ada, constructor = function.  (That is why there's a problem.)

Example:

   type LT is limited private;

   function Init (<some params>) return LT;

   ...
   declare
     O : LT := Init (...);
   begin




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00           ` Matthew Heaney
  1999-09-09  0:00             ` Robert Dewar
@ 1999-09-09  0:00             ` Mark Lundquist
  1 sibling, 0 replies; 69+ messages in thread
From: Mark Lundquist @ 1999-09-09  0:00 UTC (permalink / raw)


Matthew Heaney wrote:

> In article <37d7c116@news1.prserv.net> , "Matthew Heaney"
> <matthew_heaney@acm.org> wrote:
>
> > P.S.  Here's some more stuff I want:
>
> 1) - 7) snipped
>
> I forgot some more stuff:
>
> 8) T'Class for types that aren't tagged.
>
> 9) Controlled-ness applied to access types directly.
>
> 10) For GNAT to implement pragma Restrictions (Max_Task_Entries => 0), so
> that it can generate a more efficient RTS.
>
> 11) For GNAT to really implement Suspension_Objects, instead of just
> implementing them as a protected type.
>
> 12) For ACT to port GNAT to LinuxPPC.
>
> 13) For me to win US$1_000_000 in the lottery.

 14) "And bring back 8-tracks..."

(I think that was a line from some movie.  It must not have been that great
of a movie, 'cause all I remember is that one line :-) :-)





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

* Re: Array of Variant Records Question...
  1999-09-09  0:00           ` Robert Dewar
  1999-09-09  0:00             ` Matthew Heaney
@ 1999-09-09  0:00             ` Brian Rogoff
  1999-09-13  0:00               ` Matthew Heaney
  1999-09-10  0:00             ` Proposed Ada features (was Re: Array of Variant Records Question...) Mark Lundquist
  2 siblings, 1 reply; 69+ messages in thread
From: Brian Rogoff @ 1999-09-09  0:00 UTC (permalink / raw)


On Thu, 9 Sep 1999, Robert Dewar wrote:
> In article <37d7c116@news1.prserv.net>,
>   "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> > 1) access constant params
> 
> no comment, not exciting ...>

That's new, only exciting features may be proposed!

> > 4) implicit conversion of an access param to a named access
> type
> >
> > 5) implicit conversion of a specific access type to an access
> type that
> > designates an ancestor that is class-wide

Matt, can you give examples where you find that explicit conversions are 
painful, or damage readability?

> > 7) downward closures
> 
> discussed to death already, not worth discussing further ...

Well, if we want to be precise, we should call them "downward funargs",
since Ada already supports a restricted form of downward closure via 
generics. To violate Robert's sentiments even further, I'll append a
little GNAT program which 

(1) Uses downward funargs
(2) Has a fair bit of subprogram nesting
(3) Solves the N Queen problem

so that even if downward funargs aren't dicussable I hit two other threads :-)

Happy 9/9/99 

-- Brian

-- N Queens Problem
--
-- see L.Allison. Continuations implement generators and streams.
--     Computer Journal 33(5) 460-465 1990
--
-- Cont = State -> Answer      where State=List,  Answer=Std_output
-- Generator = Cont -> State -> Answer = Cont -> Cont

with Ada.Text_IO; use  Ada.Text_IO;

procedure Generate is
    package Int_IO is new Ada.Text_IO.Integer_IO(Integer);
    type Node_Type;
    type List_Type is access Node_Type;
    type Node_Type is
        record
            Head : Integer;
            Tail : List_Type;
        end record;

    type Cont_Proc_Type is access procedure (L : in List_Type);
    type Gen_Proc_Type  is access procedure (Cont : Cont_Proc_Type;
                                            L : in List_Type);
    type Pred_Func_Type is access function (L : in List_Type) return Boolean;

    N : Integer;

    function Cons(I : Integer; L : List_Type) return List_Type is
        P:List_Type;
    begin
      P := new Node_Type;
      P.Head := I; P.Tail := L; return P;
    end Cons;

    -- generator "library"
    -- success : Cont

    procedure Success(L : List_Type) is

        procedure Print(L : List_Type) is
        begin
            if L /= null then
                Int_IO.Put(L.Head);
                Print(L.Tail);
            end if;
        end Print;

    begin
        if L /= null then
            New_Line;
            Put(" :");
            Print(L);
        end if;
    end Success;

    -- Choose :Int -> Cont -> Cont = Int -> Generator
    procedure Choose(N : Integer; Cont : Cont_Proc_Type; L : List_Type) is
    begin
        for I in 1..n loop
            Cont( Cons(I, L) );
        end loop;
      -- for each i       continue with i++L
    end Choose;

    -- Filter : (State -> boolean) -> Generator
    procedure Filter(P    : Pred_Func_Type;
                     Cont : Cont_Proc_Type;
                     L    : List_Type) is
    begin
       if P(L) then Cont(L); end if;      -- else fail
       -- if L ok then continue with L else do nothing
    end Filter;

    -- doo = gen**n :Int -> Generator -> Generator
    procedure Doo(N    : Integer;
                  Gen  : Gen_Proc_Type;
                  Cont : Cont_Proc_Type;
                  L    : List_Type ) is

        procedure Gen_Cont(L : List_Type) is
        begin
            Gen(Cont,L);
            -- gen and then cont, to L
        end Gen_Cont;

    begin
        if N = 0 then
            Cont(L);
        else
            Doo(N-1, Gen, Gen_Cont'Unrestricted_Access, L);
        end if;
         -- do (n-1) gen and then [gen and then cont], to L
    end Doo;

    -- n queens proper
    procedure Queen(N : Integer) is
        function Valid(L : List_Type) return Boolean is
            function V(Col : Integer; L2 : List_Type) return Boolean is
            begin
              if L2 = null then
                  return True;                    -- safe
              elsif
                (L.Head = L2.Head)    or      -- check rows
                (L2.Head+Col = L.Head) or      -- & diagonals
                (L2.Head-Col = L.Head)         -- other diags
              then
                  return False;                   -- threat
              else
                  return V(col+1, L2.Tail);
              end if;
            end V;
        begin
            if L = null then
                return True;
            else
                return V(1, L.Tail);
            end if;
        end Valid;

        -- choosevalid :Generator
        procedure Choose_Valid(Cont : Cont_Proc_Type; L : List_Type) is

            procedure Valid_Cont (L : List_Type) is
            begin
                Filter(Valid'Unrestricted_Access, Cont, L);
                -- check valid and if so continue, with L
            end Valid_Cont;

        begin
            Choose(N, Valid_Cont'Unrestricted_Access, L);
            -- choose row and then [check valid and if so continue], with L
        end Choose_Valid;

    begin
        Doo(N,
            Choose_Valid'Unrestricted_Access,
            Success'Unrestricted_Access,
            Null);
          --  [do  n times: choose a valid row] and if so succeed
    end Queen;

begin
    Put_Line("Enter a number and hit return");
    Int_IO.Get(N); Queen(N); New_Line;
    Put_Line("and that's it!");
end;







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

* Re: Array of Variant Records Question...
  1999-09-09  0:00             ` Matthew Heaney
  1999-09-10  0:00               ` Robert Dewar
@ 1999-09-10  0:00               ` Mark Lundquist
  1999-09-10  0:00                 ` Matthew Heaney
  1999-09-11  0:00                 ` Robert Dewar
  1999-09-11  0:00               ` Richard D Riehle
  2 siblings, 2 replies; 69+ messages in thread
From: Mark Lundquist @ 1999-09-10  0:00 UTC (permalink / raw)


Matthew Heaney wrote:

> In article <7r8t21$ov5$1@nnrp1.deja.com> , Robert Dewar
> <robert_dewar@my-deja.com>  wrote:
>
> >> 2) the ability to cast away const w/o using
> > Sys.Addr_To_Acc_Convs
> >
> > Sorry, no idea what this means
>
> To be able to modify an in-mode subprogram parameter.  Essentially, what ACT
> did to implement the function Random in GNAT.
>

I'm not familiar with GNAT (I know, you were answering Dewar...)

Do you mean that you want to be able to modify the formal parameter?  (But if
that were the case, why is Address_To_Access_Conversion the workaround, instead
of just declaring a variable and assigning it the parameter value?)  Or do you
mean you want to modify the actual parameter, as if it were mode 'in out'?






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

* Re: Array of Variant Records Question...
  1999-09-10  0:00               ` Robert Dewar
@ 1999-09-10  0:00                 ` Mark Lundquist
  1999-09-10  0:00                   ` Matthew Heaney
  0 siblings, 1 reply; 69+ messages in thread
From: Mark Lundquist @ 1999-09-10  0:00 UTC (permalink / raw)


Robert Dewar wrote:

> In article <37d822a1@news1.prserv.net>,
>   "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> > To be able to modify an in-mode subprogram parameter.
> > Essentially, what ACT did to implement the function Random
> > in GNAT.
>
> That seems just *too* kludgy to me, and very implemention
> dependent, wouldn't it be better to just introduce in out
> and out parameters for functions (but we know that one won't
> fly ...)
>

Why would that be necessary, since functions already can have access
parameters?  OK, the actual must denote an aliased view...







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

* Re: Proposed Ada features (was Re: Array of Variant Records Question...)
  1999-09-10  0:00               ` Matthew Heaney
@ 1999-09-10  0:00                 ` tmoran
  0 siblings, 0 replies; 69+ messages in thread
From: tmoran @ 1999-09-10  0:00 UTC (permalink / raw)


> function Get_Top (Stack : Stack_Type) return Item_Type is
>   Control : Semaphore_Control (Stack.Semaphore'Access);
But the problem here is that the function Get_Top is in fact going
to modify its parameter - Stack will become unavailable to others,
at least for a while - and you want to modify the parameter to
a function.  This may be a good example of why functions should
allow "in out" parameters, but it's not a good example of why
"access constant" is desirable.




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

* Re: Array of Variant Records Question...
  1999-09-10  0:00               ` Mark Lundquist
@ 1999-09-10  0:00                 ` Matthew Heaney
  1999-09-11  0:00                 ` Robert Dewar
  1 sibling, 0 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-10  0:00 UTC (permalink / raw)


In article <37D96905.2D10D264@rational.com> , Mark Lundquist 
<mark@rational.com>  wrote:

> Do you mean that you want to be able to modify the formal parameter?

Yes.

> (But if that were the case, why is Address_To_Access_Conversion the
> workaround, instead of just declaring a variable and assigning it the
> parameter value?)

Won't work for limited types (like Generator).


> Or do you mean you want to modify the actual parameter, as if it were mode 'in
> out'?

Yes.




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

* Re: Array of Variant Records Question...
  1999-09-10  0:00                 ` Mark Lundquist
@ 1999-09-10  0:00                   ` Matthew Heaney
  1999-09-11  0:00                     ` Jean-Pierre Rosen
                                       ` (2 more replies)
  0 siblings, 3 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-10  0:00 UTC (permalink / raw)


In article <37D96965.81045235@rational.com> , Mark Lundquist 
<mark@rational.com>  wrote:

>> That seems just *too* kludgy to me, and very implemention
>> dependent, wouldn't it be better to just introduce in out
>> and out parameters for functions (but we know that one won't
>> fly ...)
>>
>
> Why would that be necessary, since functions already can have access
> parameters?  OK, the actual must denote an aliased view...


It's like I said in another post: sometimes you have an operation that is
publicly in-mode, but privately in-out.

The function Random is declared this way:

  function Random (G : in Generator) return Result_Subtype;

From an abstract point of view, Generator provides a stream of random
numbers, and function Random simply returns successive values from this
stream.  The stream is just out there, in the ether, and no modification of
this stream is required.

From an implementation point of view, however, invoking the function Random
changes the state of the Generator.  That's why you need a way to "cast away
const," to be able to change state of an object whose parameter mode is in.

The AARM suggests a way to implement this type, by using a level of
indirection.  However, this means allocating the internal state on the heap,
and implementing Generator by privately deriving from Limited_Controlled (to
reclaim the memory).  This is an awfully heavy solution, compared to the
alternative.

Now you're right, you could declare Random this way:

  function Random (G : access Generator) return Result_Subtype;

and everything would be hunky-dory.

But how would you feel about actually using that function:

  declare
    G : aliased Generator;
  begin
    ... Random (G'Access) ...
  end;

Compare that to:

  declare
    G : Generator;
  begin
    ... Random (G) ...
  end;





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

* Re: Array of Variant Records Question...
  1999-09-09  0:00       ` Tucker Taft
@ 1999-09-10  0:00         ` Nick Roberts
  0 siblings, 0 replies; 69+ messages in thread
From: Nick Roberts @ 1999-09-10  0:00 UTC (permalink / raw)


Please find below an  article I posted on comp.lang.ada in March this year.
Please forgive the length of it.

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

It dawns on me that Ada provides special syntax for singletons of two
particular kinds of types: tasks and protected objects.  Perhaps it would
not be too drastic to provide for singletons of tagged types?

Given a base type:

  type Pop_Star is [abstract] tagged ...;

with an operation such as:

  procedure Exploit (Star: in [out] Pop_Star; Creaming_Off: out Money) [is
abstract];

we might allow a 'single extension declaration':

  Elvis: [aliased] [constant] new Pop_Star with
      record
        ...
      end record;

or a 'single private extension declaration':

  Elvis: [aliased] [constant] new Pop_Star with private;

which would then have to be privately completed by a full single extension.

The object 'Elvis' would be of an anonymous tagged type.  It would not be
possible to derive from this anonymous type, because it could not be named.
The Tag attribute would be applicable to an object such as 'Elvis', but not
the Class attribute.  The 'in' operation would be applicable to such objects
(but probably not often used).

A 'single-object' parameter form could be used within subprogram
declarations:

  procedure Exploit (for [constant] Elvis; Creaming_Off: out Money);

The 'constant' would be required for an 'in' parameter, and omitted for an
'out', 'in out', or 'access' parameter.  These subprograms would be
primitive operations of the anonymous type of the object 'Elvis' (if
declared within the same package specification).

A totally separate, but also useful idea, it occurs to me, would be
'polymorphic arrays': arrays which have an indefinite component subtype.

Supposing we extended the Pop_Star hierarchy:

  type Singer is new Pop_Star with ...;
  type Violinist is new Pop_Star with ...;
  type Drummer is new Pop_Star with ...;
  type Guitarist is new Pop_Star with ...;

We could then use an array object declaration to create an array of objects
of different, but related, types:

  type Corr_Name is (Andrea, Sharon, Caroline, Jim);

  Corrs: [aliased] [constant] array (Corr_Name) of Pop_Star'Class (Singer,
Violinist, Drummer, Guitarist);

At the end of this declaration is a new piece of syntax: the 'polymorphic
array type association'.  This is like an aggregate (and allows named
associations like an aggregate), but only specifies types (which must all be
definite).  Once the types of the components of one of these arrays are set,
they cannot be changed (i.e. the array is permanently constrained).

Alternatively, an initialisation can be used specify the different types of
the components:

  Corrs: [aliased] [constant] array (Corr_Name) of Pop_Star'Class :=
(Andrea => (Singer with ...), Sharon => (Violinist with ...), Caroline =>
(Drummer with ...), Jim => (Guitarist with ...));

This demonstrates a new form of array aggregate -- a 'polymorphic array
aggregate' -- that could never be legal in Ada at present.  As usual, an
initialisation could be used in addition to a type association, in which
case the types must all match.

A named polymorphic array type could be declared:

  type Pop_Group is array (Positive range <>) of [aliased] Pop_Star'Class;

and then objects of this type could be declared, e.g.:

  Spice_Girls: Pop_Group(1..4)(others => Singer);

  Metallica: Pop_Group :=
      (1 => (Singer with ...), 2|3 => (Guitarist with ...), 4 => (Drummer
with ...));

and the usual operations would then be available:

  Brian_Adams: Singer;

  Super_7: Pop_Group(1..7) := Spice_Girls(2..3) & Metallica & Brian_Adams;

Implementation of these types would be a cinch (probably just an array of
pointers plus a block of data), and they would be terrifically useful.  A
classic example is the 'sparse array' (one which has more holes in it than
you would care to waste memory on).  Another is the 'array of strings',
e.g.:

  Messages: constant array (1..100) of String :=
      (1 => "Error: you must put the milk in before the tea",       2 =>
"Error: you must extend your little finger when holding the cup",
      ...);

Doing the equivalent of this in Ada 95 is still a pain.

More ideas for Ada 200X?  (Yet more :-)

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

When I suggest an implementation of an array of pointers and a block of
data, I think both Tucker and Robert Dewar misunderstand: I don't intend the
data - either in a block or individually - to be allocated on the heap
(unless the whole array is). They can both be allocated in the same place
(the stack for variables, constant data space for constants, or wherever).
This is because the polymorphic array type that I suggest is always either
completely unconstrained or completely constrained: when it's constrained,
the size of both the array of pointers and the block of data of an object of
the type is known and fixed; when it's unconstrained, an object of the type
cannot be declared. Simple, straightforward, and efficient.

I would be interested in making this a formal proposal for the next revision
of Ada (if someone would be kind enough to tell me how :-), together with
the singleton tagged type as well. I would appreciate help!

Tucker says this idea "does not seem to be providing significant new
capability that cannot be programmed already using existing features."  I
disagree. I think it's a feature that would be extremely useful, and not
just a nicety. Consider the constant array of strings example.

Best wishes,

-------------------------------------
Nick Roberts
http://www.adapower.com/lab/adaos
-------------------------------------

Tucker Taft <stt@averstar.com> wrote in message
news:37D7B099.8C1A5CC6@averstar.com...
| Nick Roberts wrote:
| >
| > The flaw is that Ada has no 'polymorphic array type': an array that has
an
| > indefinite component subtype.
| >
| > As I suggested in a post a few months ago, such an array type would be
easy
| > to add to Ada's existing syntax, easy and efficient to implement (as an
| > array of pointers plus a ragged sequence of objects, internally), and
very
| > bloody useful, pardon the language. (It would have solved Bruce's
problem in
| > a trice.)
|
| We considered full support for "indefinite"/unconstrained subtypes
| during the Ada 9X process, but ultimately decided to avoid any
| language feature that would require implicit levels of indirection
| within an object.  The general philosophy here is that levels of
indirection
| should be under the control of the programmer, not the compiler.
| You can certainly create a structure much like what you propose by
| an array of pointers, initialized with a sequence of allocators.
| The benefits from building such a capability into the language
| itself would probably not justify the added complexity, particularly
| when you consider the fine level of representation control Ada programmers
| desire over data structures.
|
| >
| > Maybe come the next review...
|
| If you have a detailed proposal with examples, ACVC tests, etc., feel free
| to document it.  However, don't hold your breath for this to happen,
| since (at least as far as I understand it) does not seem to be providing
| significant new capability that cannot be programmed already using
| existing features.







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

* Re: Array of Variant Records Question...
  1999-09-09  0:00             ` Matthew Heaney
@ 1999-09-10  0:00               ` Robert Dewar
  1999-09-10  0:00                 ` Mark Lundquist
  1999-09-10  0:00               ` Mark Lundquist
  1999-09-11  0:00               ` Richard D Riehle
  2 siblings, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-10  0:00 UTC (permalink / raw)


In article <37d822a1@news1.prserv.net>,
  "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> To be able to modify an in-mode subprogram parameter.
> Essentially, what ACT did to implement the function Random
> in GNAT.

That seems just *too* kludgy to me, and very implemention
dependent, wouldn't it be better to just introduce in out
and out parameters for functions (but we know that one won't
fly ...)

>
> >> 6) the ability to invoke a constructor/initializer for
limited types in the
> >> declarative region
> >
> > sorry, I do not know what you mean here, and I certainly
> > do not know what a constructor is, example would be useful.
>
> In Ada, constructor = function.  (That is why there's a
problem.)
>
> Example:
>
>    type LT is limited private;
>
>    function Init (<some params>) return LT;
>
>    ...
>    declare
>      O : LT := Init (...);
>    begin
>

OK, I see, yes, something like that would be useful indeed ...


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Proposed Ada features (was Re: Array of Variant Records Question...)
  1999-09-09  0:00           ` Robert Dewar
  1999-09-09  0:00             ` Matthew Heaney
  1999-09-09  0:00             ` Array of Variant Records Question Brian Rogoff
@ 1999-09-10  0:00             ` Mark Lundquist
  1999-09-10  0:00               ` Matthew Heaney
  2 siblings, 1 reply; 69+ messages in thread
From: Mark Lundquist @ 1999-09-10  0:00 UTC (permalink / raw)


Robert Dewar wrote:

> In article <37d7c116@news1.prserv.net>,
>   "Matthew Heaney" <matthew_heaney@acm.org> wrote:
> > 1) access constant params

Yes.

And Matt, don't forget "is limited access"... As I recall you were the
one who mentioned this a while back, but for some reason it didn't make
your wish list (or, it's far enough behind "winning the lottery" not to
merit mention :-)  I have had exactly the same wish (for limited access
types, not the lottery :-)  and it came up in exactly the same
context: I was implementing a generic mixin for reference-counted
memory-managed objects, and the non-limitedness of the access type
breaks reference safety.

On the other hand, the unsafe access type would be useful for local
assignments (e.g. a swap) where you know that a
"lightweight" (uncounted) assignment will do.  So I'm equivocating a
little.  I couldn't think of a workaround that would ensure that you are
using the unsafe mechansim in a way that is in fact safe.

>

>

>
>
> > 2) the ability to cast away const w/o using
> Sys.Addr_To_Acc_Convs
>
> Sorry, no idea what this means

...from the speech of barbarians, there is no translation in our
tongue... :-) :-) :-) :-)

Here's my understanding of it.  I'm not at all sure that it's accurate,
maybe someone can help me out...
In C++, 'const' is more like an attribute of the type than of the
object.  Given an object of a 'const type' (typically a function
parameter), you can render that object assignable by means of a cast
(conversion) to a 'non-const type'.  In C you would use the "(type)"
syntax, and in C++ you would use the built-in template function
const_cast<type>().  This formula is known as "casting away const"
(because you are not really changing the type per se, just the
"constness").

What I haven't figured out is why you would want to do this.  Same with
"mutable".

> > 6) the ability to invoke a constructor/initializer for limited
> types in the
> > declarative region
>
> sorry, I do not know what you mean here, and I certainly
> do not know what a constructor is, example would be useful.

I think in Ada, it would just be a function call as an initialization
expression.  The idea is to allow this for limited types.





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

* Re: Proposed Ada features (was Re: Array of Variant Records Question...)
  1999-09-10  0:00             ` Proposed Ada features (was Re: Array of Variant Records Question...) Mark Lundquist
@ 1999-09-10  0:00               ` Matthew Heaney
  1999-09-10  0:00                 ` tmoran
  0 siblings, 1 reply; 69+ messages in thread
From: Matthew Heaney @ 1999-09-10  0:00 UTC (permalink / raw)


In article <37D955B5.A018835D@rational.com> , Mark Lundquist 
<mark@rational.com>  wrote:


> And Matt, don't forget "is limited access"... As I recall you were the
> one who mentioned this a while back, but for some reason it didn't make
> your wish list.

It's implied by the downward funarg request.  Limited access types have been
proposed as a (partial?) solution to that problem.

The reason I want "access constant" params is to be able to use the
automatic resource locking idiom, without having to use Chap 13 tricks.

I'll use my fav example.  Suppose we have a concurrent stack.  A semaphore
is part of the representation of the stack, and it's used to Seize and
Release the stack at the beginning and end of every stack operation.

For example, the Semaphore_Control type looks like this:

  type Semaphore_Control (Semaphore : access Semaphore_Type) is
    limited private;

Semaphore_Control type privately derives from Limited_Controlled, and calls
Semaphore.Seize during Initialize, and Semaphore.Release during Finalize.

To implement Push, you'd do this:

  procedure Push
    (Item  : in     Item_Type;
     Stack : in out Stack_Type) is

     Control : Semaphore_Control (Stack.Semaphore'Access);
  begin
    Stack.Top := Stack.Top + 1;
    Stack.Items (Stack.Top) := Item;
  end;

Everything's hunky-dory here, because the Stack is a variable view.  (Let's
assume it's also an aliased view, because the stack is either publicly or
privately tagged.)

But now let's try to implement Get_Top:

  function Get_Top (Stack : Stack_Type) return Item_Type is

    Control : Semaphore_Control (Stack.Semaphore'Access);
  begin
    return Stack.Items (Stack.Top);
  end;

This code is illegal, because this is a constant view of the Stack, not a
variable view.  The access discriminant of the Control object requires a
variable view.

However, if we were able to declare the Control object this way:

  type Semaphore_Control (Semaphore : access constant Semaphore_Type) is
    limited private;

then only a constant view of the Stack is necessary, and Get_Top can be
implemented as I've shown above.

Now, there are two ways to solve the problem:

1) Pass the stack as an access parameter to Get_Top.

This works, but it makes it seem as if the Stack is being modified during
Get_Top.  Worse, it makes it impossible to invoke Get_Top in a context where
we have a read-only view of the stack.

So we prefer to implement Get_Top using an in-mode param.


2) Use System.Address_To_Access_Conversions.

The stack is a by-reference type, so Stack'Address is legal(?) per RM95 13.3
(16).  We feed the Stack's address to To_Pointer, which gives us an access
object designating a variable view of the Stack.  We then refer to the Stack
via the access object, instead of via the in-mode parameter.

I would prefer to not ever have to invoke RM95 13.3 (16), but now I often
have to, being careful to always implement the type in such a way as to
guarantee that it's passed by-reference.


Another time this would be handy is to implement a factory method
constructor for iterators.  For example, suppose I want to do implement a
class-wide operation to print a stack (useful for debugging):

  procedure Print (Stack : in Root_Stack_Type'Class) is

    Iterator : Root_Iterator_Type'Class :=
      Start_At_Top (Stack'Access);
  begin

The factory method looks like this:

  function Start_At_Top
    (Stack : access Root_Stack_Type)
    return Root_Iterator_Type'Class;

The iterator needs a pointer to the stack, AND Start_At_Top needs to be
primitive, so it will dispatch.  That means an access parameter.

But, the invokation above is illegal, because I can't take the 'Access of a
constant view of the stack.  However, if I were able to declare the factory
method this way:

  function Start_At_Top
    (Stack : access constant Root_Stack_Type)
    return Root_Iterator_Type'Class;

then everything would be hunky-dory.

I solve the problem now by passing the stack as an in-mode parameter, and
internally turn that into an access object.  However, I lose all the
accessibility checks, so I'm depending on users to Do The Right Thing.


I discuss these techniques in several posts I've submitted to the ACM Ada95
Design Patterns list, and will be discussing them again in my Design
Patterns tutorial at this year's SIGAda conference.

<http://www.acm.org/archives/patterns.html>

(Search for "13.3", and see what drops out.)


>> > 2) the ability to cast away const w/o using
>> Sys.Addr_To_Acc_Convs
> What I haven't figured out is why you would want to do this.  Same with
> "mutable".

This is closely related to the problem above.

Basically, what I really want is functions with in-out parameters, but this
will never happen.  However, you do get most of what you need already, by
passing the object as an access parameter.

You could argue for its inclusion for the same reasons it's in C++.
Sometimes, you have an operation that, publicly, doesn't change the state of
the object.  But privately, it may make sense to make a state change, say,
to record some information about the call.

The canonical example of this is the function Random.  It changes the state
of the Generator, which is an in-mode parameter.




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

* Re: Array of Variant Records Question...
  1999-09-10  0:00               ` Mark Lundquist
  1999-09-10  0:00                 ` Matthew Heaney
@ 1999-09-11  0:00                 ` Robert Dewar
  1 sibling, 0 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-11  0:00 UTC (permalink / raw)


In article <37D96905.2D10D264@rational.com>,
  Mark Lundquist <mark@rational.com> wrote:
> Matthew Heaney wrote:
>
> > In article <7r8t21$ov5$1@nnrp1.deja.com> , Robert Dewar
> > <robert_dewar@my-deja.com>  wrote:
> >
> > >> 2) the ability to cast away const w/o using
> > > Sys.Addr_To_Acc_Convs
> > >
> > > Sorry, no idea what this means
> >
> > To be able to modify an in-mode subprogram parameter.
Essentially, what ACT
> > did to implement the function Random in GNAT.
> >
>
> I'm not familiar with GNAT (I know, you were answering
Dewar...)

No, but you are familiar with Ada 95 :-)

You have a look at the spec of random, and see if you can
figure out any reasonable way to implement it in pure Ada,
I certainly can't!


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-10  0:00                   ` Matthew Heaney
@ 1999-09-11  0:00                     ` Jean-Pierre Rosen
  1999-09-14  0:00                     ` "cast away const" (was Re: Array of Variant Records Question...) Mark Lundquist
       [not found]                     ` <wccd7viiv59.fsf@world.std.com>
  2 siblings, 0 replies; 69+ messages in thread
From: Jean-Pierre Rosen @ 1999-09-11  0:00 UTC (permalink / raw)


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


Matthew Heaney <matthew_heaney@acm.org> a �crit dans le message :
37d9a3b7@news1.prserv.net...
> In article <37D96965.81045235@rational.com> , Mark Lundquist
> <mark@rational.com>  wrote:
>
[Discussion about modifying in parameters snipped]

Actually, there is a way of modifiying an in parameter, if you can accept it
is limited:

Type T is limited private;
function F (X : in T) return ...;

...
private
   type Relay (Reference : access T) is limited null record;
   type T is
      record
         Myself  : Relay (T'Access);
         -- other components
      end record;


Inside function F, you are not allowed to modifiy X, but you are allowed to
modify X.Myself.all ....

--
---------------------------------------------------------
           J-P. Rosen (Rosen.Adalog@wanadoo.fr)
Visit Adalog's web site at http://perso.wanadoo.fr/adalog







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

* Re: Array of Variant Records Question...
  1999-09-09  0:00             ` Matthew Heaney
  1999-09-10  0:00               ` Robert Dewar
  1999-09-10  0:00               ` Mark Lundquist
@ 1999-09-11  0:00               ` Richard D Riehle
  1999-09-13  0:00                 ` Hyman Rosen
  1999-09-14  0:00                 ` Mark Lundquist
  2 siblings, 2 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-11  0:00 UTC (permalink / raw)


In article <37d822a1@news1.prserv.net>,
	"Matthew Heaney" <matthew_heaney@acm.org> wrote:

>To be able to modify an in-mode subprogram parameter.  Essentially, what
ACT
>did to implement the function Random in GNAT.
>
>(The locution "cast away const" comes from C++.)

One of things I do not like about the current C++ standard is the
kludge that permits "cast away const".  Would not want this in Ada.
However, I do like the stronger model for const that C++ provides 
and would like to see constant functions in the next version of
Ada.  For example,

      constant function (X : access Item) return T:

or even

     function (X : constant Item) return T;

where X, in both cases, can be an access to object or access type
for a function and disallows any side-effects on the components of
the parameter.  It seems to me this would be a simple fix to 
const'ness and correspond to the current behavior of a protected
function.  

Richard Riehle
http://www.adaworks.com

      




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

* Re: Array of Variant Records Question...
  1999-09-09  0:00             ` Array of Variant Records Question Brian Rogoff
@ 1999-09-13  0:00               ` Matthew Heaney
  1999-09-13  0:00                 ` Robert A Duff
  1999-09-13  0:00                 ` Brian Rogoff
  0 siblings, 2 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-13  0:00 UTC (permalink / raw)


In article <Pine.BSF.4.10.9909091910250.12989-100000@shell5.ba.best.com> ,
Brian Rogoff <bpr@shell5.ba.best.com>  wrote:

> Matt, can you give examples where you find that explicit conversions are
> painful, or damage readability?

Consider the Interpreter pattern.  An And_Exp is a Bool_Exp object with two
components, a left exp and a right exp.

The spec looks like this:


package Bool_Exps.And_Exps is

   type And_Exp is new Bool_Exp with private;

   function New_And
     (L, R : access Bool_Exp'Class)
      return Bool_Exp_Access;

    ...

private

   type And_Exp is
     new Bool_Exp with record
        L, R : Bool_Exp_Access;
     end record;

end Bool_Exps.And_Exps;


As you can see above, the constructor for the type accepts two access
parameters, and returns a pointer to the class-wide root type, which is
defined as

  type Bool_Exp_Access is access all Bool_Exp'Class;


Here's the implementation of the constructor:

   function New_And
     (L, R : access Bool_Exp'Class)
      return Bool_Exp_Access is

      use And_Exp_Storage;

      Exp : constant Exp_Access := New_Exp;
      -- type Exp_Access is access all And_Exp;
   begin
      Exp.L := Bool_Exp_Access (L);    -- (1)
      Exp.R := Bool_Exp_Access (R);    -- (2)

      return Bool_Exp_Access (Exp);    -- (3)
   end New_And;


Observe the following:

(1) L is an access parameter.  I have to manually convert

  L : access Bool_Exp'Class

to an access value of type

  type Bool_Exp_Access is access all Bool_Exp'Class;

What's the point?


(2) Same for R as for L in (1).

(3) Exp is an access object designating an And_Exp value.  I have to
manually convert an access value from

  type Exp_Access is access all And_Exp;

to an access value of

  type Bool_Exp_Access is access all Bool_Exp'Class;

But what's the point?  An And_Exp value is in And_Exp, but it's also in
Bool_Exp'Class.

The issue is that a tagged object kinda sorta has potentially many types:
it's own specific type, and the class-wide type of each of its ancestors.

I would prefer that all these manually conversions be done implicitly, so I
could just write:

   function New_And
     (L, R : access Bool_Exp'Class)
      return Bool_Exp_Access is

      use And_Exp_Storage;

      Exp : constant Exp_Access := New_Exp;
   begin
      Exp.L := L;
      Exp.R := R;

      return Exp;
   end New_And;


It's not a show-stopper though...





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

* Re: Array of Variant Records Question...
  1999-09-13  0:00               ` Matthew Heaney
@ 1999-09-13  0:00                 ` Robert A Duff
  1999-09-13  0:00                   ` Matthew Heaney
  1999-09-13  0:00                 ` Brian Rogoff
  1 sibling, 1 reply; 69+ messages in thread
From: Robert A Duff @ 1999-09-13  0:00 UTC (permalink / raw)


"Matthew Heaney" <matthew_heaney@acm.org> writes:

> In article <Pine.BSF.4.10.9909091910250.12989-100000@shell5.ba.best.com> ,
> Brian Rogoff <bpr@shell5.ba.best.com>  wrote:
> 
> > Matt, can you give examples where you find that explicit conversions are
> > painful, or damage readability?

In my opinion, every conversion in the upward direction (toward the root
of the hierarchy) damages readability, because it obscures the
conversions in the other direction, which are somewhat dangerous (can
raise an exception).  It's like the boy who cried wolf.  If you yell and
scream when there's no danger, people won't pay attention when there
*is* a danger.

So I agree with Matt that upward conversions should be implicit.
On the other hand, I think requiring downward conversions to be explicit
serves a useful purpose.

> Consider the Interpreter pattern.  An And_Exp is a Bool_Exp object with two
> components, a left exp and a right exp.
> 
> The spec looks like this:
> 
> 
> package Bool_Exps.And_Exps is
> 
>    type And_Exp is new Bool_Exp with private;
> 
>    function New_And
>      (L, R : access Bool_Exp'Class)
>       return Bool_Exp_Access;
> 
>     ...
> 
> private
> 
>    type And_Exp is
>      new Bool_Exp with record
>         L, R : Bool_Exp_Access;
>      end record;

Have you considered:

    type And_Exp(L, R : access Bool_Exp'Class) is
      new Bool_Exp with null record;

?

> end Bool_Exps.And_Exps;
> 
> 
> As you can see above, the constructor for the type accepts two access
> parameters, and returns a pointer to the class-wide root type, which is
> defined as
> 
>   type Bool_Exp_Access is access all Bool_Exp'Class;
> 
> 
> Here's the implementation of the constructor:
> 
>    function New_And
>      (L, R : access Bool_Exp'Class)
>       return Bool_Exp_Access is
> 
>       use And_Exp_Storage;
> 
>       Exp : constant Exp_Access := New_Exp;
>       -- type Exp_Access is access all And_Exp;
>    begin
>       Exp.L := Bool_Exp_Access (L);    -- (1)
>       Exp.R := Bool_Exp_Access (R);    -- (2)
> 
>       return Bool_Exp_Access (Exp);    -- (3)
>    end New_And;

Something's wrong with that.  How can New_Exp know to allocate an
And_Exp record?  And the "Exp.L" and "Exp.R" are illegal, because
there's (presumably) no such components?  I'm confused.

How about:

    return new Bool_Exp'(Bool_Exp_Access(L), Bool_Exp_Access(R));

which avoids the need for one of the conversions?

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




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

* Re: Array of Variant Records Question...
  1999-09-13  0:00                 ` Robert A Duff
@ 1999-09-13  0:00                   ` Matthew Heaney
  0 siblings, 0 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-13  0:00 UTC (permalink / raw)


In article <wccyaeakcf0.fsf@world.std.com> , Robert A Duff 
<bobduff@world.std.com>  wrote:

> Have you considered:
>
>     type And_Exp(L, R : access Bool_Exp'Class) is
>       new Bool_Exp with null record;
>
> ?


No, not here, though I've used this technique for another pattern (the
Command pattern).


>>    function New_And
>>      (L, R : access Bool_Exp'Class)
>>       return Bool_Exp_Access is
>>
>>       use And_Exp_Storage;
>>
>>       Exp : constant Exp_Access := New_Exp;
>>       -- type Exp_Access is access all And_Exp;
>>    begin
>>       Exp.L := Bool_Exp_Access (L);    -- (1)
>>       Exp.R := Bool_Exp_Access (R);    -- (2)
>>
>>       return Bool_Exp_Access (Exp);    -- (3)
>>    end New_And;
>
> Something's wrong with that.  How can New_Exp know to allocate an
> And_Exp record?

New_Exp is provided by a private generic storage manager that looks like
this:

  private generic
    type Exp_Type is new Bool_Exp with private;
  package Bool_Exps.Storage is

    type Exp_Access is access all Exp_Type;

    function New_Exp return Exp_Access;

    procedure Do_Free (Exp : access Exp_Type);

  end Bool_Exps.Storage;

The package is instantiated like this:

  package And_Exp_Storage is
    new Storage (And_Exp);


> And the "Exp.L" and "Exp.R" are illegal, because
> there's (presumably) no such components?  I'm confused.

Yes, there are L and R components.  Here's what an And_Exp looks like:

    type And_Exp is
      new Bool_Exp with record
         L, R : Bool_Exp_Access;
      end record;

You need New_Exp to return the specific type, precisely to give you access
to the representation of the type.

But after you fill in the components, you have to (manually) convert it back
to the class-wide root type.


> How about:
>
>     return new Bool_Exp'(Bool_Exp_Access(L), Bool_Exp_Access(R));
>
> which avoids the need for one of the conversions?

But I think you really meant:

  return new And_Exp'(...);

In my implementation, all allocation goes through some storage manager.
(There's a separate instantiation for each specific type in the class.)

I'll be discussing the Interpreter pattern in my upcoming Design Patterns
tutorial at this year's SIGAda conference.  You're going to be there too,
right?  Maybe you and I can finally get to meet face-to-face...

Matt




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

* Re: Array of Variant Records Question...
  1999-09-13  0:00               ` Matthew Heaney
  1999-09-13  0:00                 ` Robert A Duff
@ 1999-09-13  0:00                 ` Brian Rogoff
  1999-09-14  0:00                   ` Robert Dewar
  1999-09-14  0:00                   ` Robert Dewar
  1 sibling, 2 replies; 69+ messages in thread
From: Brian Rogoff @ 1999-09-13  0:00 UTC (permalink / raw)


On Mon, 13 Sep 1999, Matthew Heaney wrote:

> In article <Pine.BSF.4.10.9909091910250.12989-100000@shell5.ba.best.com> ,
> Brian Rogoff <bpr@shell5.ba.best.com>  wrote:
> 
> > Matt, can you give examples where you find that explicit conversions are
> > painful, or damage readability?

... examples snipped ...

> It's not a show-stopper though...

I agree that the conversions are annoying, and since the implementation 
impact of fixing this appears negligible, we could do without them, but I
don't find this any worse than the other cases in Ada where you have to
say more than you really want. In fact, I find it considerably less
annoying than those cases where I have to explicitly instantiate a
generic subprogram when it is fairly obvious what I want. 

I'd really like to reconsider this entire idea of what is better for 
the reader and maintainer of code, since it is by no means clear that 
there is widespread consensus on what is more readable. Here is another 
example where being explicit is considered by some to be an impediment to 
readability.

-- Brian






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

* Re: Array of Variant Records Question...
  1999-09-11  0:00               ` Richard D Riehle
@ 1999-09-13  0:00                 ` Hyman Rosen
  1999-09-14  0:00                 ` Mark Lundquist
  1 sibling, 0 replies; 69+ messages in thread
From: Hyman Rosen @ 1999-09-13  0:00 UTC (permalink / raw)


Richard D Riehle <laoXhai@ix.netcom.com> writes:
> One of things I do not like about the current C++ standard is the
> kludge that permits "cast away const".  Would not want this in Ada.

It's not a kludge, any more than unchecked conversion is. I suspect
that C++'s greatest need for const_cast comes from having to support
old C libraries which did not use const in their interfaces. You
have a function which takes a 'char *' rather than a 'char const *'
parameter, but the documentation of the function promises that it
leaves the contents unchanged. You have a 'char const *' that you
need to pass to this function. So you cast away const.




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

* Re: Array of Variant Records Question...
  1999-09-13  0:00                 ` Brian Rogoff
@ 1999-09-14  0:00                   ` Robert Dewar
  1999-09-14  0:00                   ` Robert Dewar
  1 sibling, 0 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-14  0:00 UTC (permalink / raw)


In article
<Pine.BSF.4.10.9909132149240.5540-100000@shell5.ba.best.com>,
  Brian Rogoff <bpr@shell5.ba.best.com> wrote:
> I'd really like to reconsider this entire idea of what is
better for
> the reader and maintainer of code, since it is by no means
clear that
> there is widespread consensus on what is more readable. Here
is another
> example where being explicit is considered by some to be an
impediment to
> readability.


You don't really want to reconsider the "entire idea", you just
want to discuss in a particular case what really does help or
not help readability. There is never unanimous agreement in
this area (consider for example the case of use clauses), but
the principle is an important one. There is no rule that says
making things explicit always helps readability!


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-13  0:00                 ` Brian Rogoff
  1999-09-14  0:00                   ` Robert Dewar
@ 1999-09-14  0:00                   ` Robert Dewar
  1999-09-14  0:00                     ` Brian Rogoff
  1 sibling, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-14  0:00 UTC (permalink / raw)


In article
<Pine.BSF.4.10.9909132149240.5540-100000@shell5.ba.best.com>,
  Brian Rogoff <bpr@shell5.ba.best.com> wrote:
> In fact, I find it considerably less
> annoying than those cases where I have to explicitly
instantiate a
> generic subprogram when it is fairly obvious what I want.

Note that you gave the writer's point of view here, Your
point would have been stronger if you had said that it
was annoying to read someone else's code in which there is
an explicit instantiation which is obvious.

(I personally do NOT agree that implicit instantiations help
readability)


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* "cast away const" (was Re: Array of Variant Records Question...)
  1999-09-10  0:00                   ` Matthew Heaney
  1999-09-11  0:00                     ` Jean-Pierre Rosen
@ 1999-09-14  0:00                     ` Mark Lundquist
       [not found]                     ` <wccd7viiv59.fsf@world.std.com>
  2 siblings, 0 replies; 69+ messages in thread
From: Mark Lundquist @ 1999-09-14  0:00 UTC (permalink / raw)


Matthew Heaney wrote:

> In article <37D96965.81045235@rational.com> , Mark Lundquist
> <mark@rational.com>  wrote:
>
> >> That seems just *too* kludgy to me, and very implemention
> >> dependent, wouldn't it be better to just introduce in out
> >> and out parameters for functions (but we know that one won't
> >> fly ...)
> >>
> >
> > Why would that be necessary, since functions already can have access
> > parameters?  OK, the actual must denote an aliased view...
>
> It's like I said in another post: sometimes you have an operation that is
> publicly in-mode, but privately in-out.
>
> The function Random is declared this way:
>
>   function Random (G : in Generator) return Result_Subtype;
>
> From an abstract point of view, Generator provides a stream of random
> numbers, and function Random simply returns successive values from this
> stream.  The stream is just out there, in the ether, and no modification of
> this stream is required.

At this level of abstraction, something like a self-advancing iterator would
look similar.  It's not that much of a stretch, even though everyone knows that
the iterator must have state and that the state must change when the iterator
advances.  But it's not like you really want to say "extract the value, and oh
by the way update the iterator, too..."  You really just mean, "I'm giving you
the iterator to operate on", i.e., in-mode.

>

> From an implementation point of view, however, invoking the function Random
> changes the state of the Generator.  That's why you need a way to "cast away
> const," to be able to change state of an object whose parameter mode is in.

I've been trying think from your "abstract point of view" about objects whose
type view is limited private.  What exactly can "state" mean from this
perspective?  You don't know about its components, can't assign it, can't test
equality.  Isn't the idea "state" of an opaque object kind of problematic?
Suppose that in the bodies of primitives of types whose partial view is limited
private, an in-mode parameter declared a variable view instead of a constant
view (in other words, if the differentiation of in-mode vs. in-out-mode were
annulled).  A bizzarre idea on the face of it, but -- what would be lost?
(Not that I think this would actually be a good idea...)

Why do we have parameter modes in the first place? It's so that intent is
communicated explicitly, esp. to programmers who are going to code against the
subprogram declaration.  We could have only mode in-out, as is the case in Java
-- then it's this expressiveness that would be lost, but in the case of limited
private types it sort of collapses.

If the language adopted your cast-away-const operation, should it be available
only for types whose partial view is limited private, and then only where the
full view is visible (i.e. in the body?)






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

* Re: Array of Variant Records Question...
  1999-09-11  0:00               ` Richard D Riehle
  1999-09-13  0:00                 ` Hyman Rosen
@ 1999-09-14  0:00                 ` Mark Lundquist
       [not found]                   ` <7roohh$s6r@dfw-ixnews7.ix.netcom.com>
  1 sibling, 1 reply; 69+ messages in thread
From: Mark Lundquist @ 1999-09-14  0:00 UTC (permalink / raw)


Richard D Riehle wrote:

> <...>

> However, I do like the stronger model for const that C++ provides

Me too... (cf. the posts discussing Matt's proposed "access
constant" parameters)

> and would like to see constant functions in the next version of
> Ada.  For example,
>
>       constant function (X : access Item) return T:
>
> or even
>
>      function (X : constant Item) return T;
>
> where X, in both cases, can be an access to object or access type
> for a function and disallows any side-effects on the components of
> the parameter.

Sorry, I'm not following at all.  What are these supposed to mean?  Did you
leave out the identifier by mistake?

Certainly the idea of a C++ -like "const function" is nonsensical for Ada.
The meaning and necessity of C++'s const functions are intrisically linked
to the idea of "member functions" and distinguished-receiver syntax, which
we fortunately don't have in Ada.  So you can't mean that...

In a sense, "const functions" in C++ are one of the workarounds for
class-oriented OO...





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

* Re: Array of Variant Records Question...
  1999-09-14  0:00                   ` Robert Dewar
@ 1999-09-14  0:00                     ` Brian Rogoff
  0 siblings, 0 replies; 69+ messages in thread
From: Brian Rogoff @ 1999-09-14  0:00 UTC (permalink / raw)


On Tue, 14 Sep 1999, Robert Dewar wrote:
> In article
> <Pine.BSF.4.10.9909132149240.5540-100000@shell5.ba.best.com>,
>   Brian Rogoff <bpr@shell5.ba.best.com> wrote:
> > In fact, I find it considerably less
> > annoying than those cases where I have to explicitly
> instantiate a
> > generic subprogram when it is fairly obvious what I want.
> 
> Note that you gave the writer's point of view here, Your
> point would have been stronger if you had said that it
> was annoying to read someone else's code in which there is
> an explicit instantiation which is obvious.

You are correct. Having read much C++ code which uses *some* implicit 
instantiations, I have to say it is much easier to read than similar Ada 
which forces you to be explicit about everything. Take into consideration 
that I find C++ syntax horrible in comparison with Ada, and I think you 
can infer that at least in my case, implicit instantiation can be
beneficial for the reader. 

> (I personally do NOT agree that implicit instantiations help
> readability)

Would you care to elaborate? Do you think implicit instantiations hinder 
readability? Do you think they *never* help readability? Your
parenthesized comment admits too many interpretations. 

Many programming language designers seem to think that overloading
seriously hinders readability too. I think that optional implicit
instantiation is very much like overloading: used well it leads to 
more readable code but I can imagine that used carelessly it could 
be problematic.

-- Brian






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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
       [not found]                             ` <wccemfxn15s.fsf@world.std.com>
@ 1999-09-22  0:00                               ` Richard D Riehle
  0 siblings, 0 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-22  0:00 UTC (permalink / raw)


In article <wccemfxn15s.fsf@world.std.com>,
	Robert A Duff <bobduff@world.std.com> wrote:

>Richard D Riehle <laoXhai@ix.netcom.com> writes:
>
>>      Extremism in a defense against side-effects is no vice. :-)
>
>I see the smily, but:
>
>IMHO a language design should not attempt to prevent "evil".  Instead,
>it should help the programmer mark the dangerous or questionable things
>clearly.  Eg, Unchecked_Conversion isn't evil ...

I agree that unchecked_conversion isn't evil.  Nor are the other unchecked
services provided by the language.  In fact, the very way they are provided
supports the notion of Ada's default of "safe" while permitting a designer
to relax that default when necessary.  

The default access parameters is "unsafe". I am simply suggesting that a
constant designation in the parameter list would ensure a safer implementation,
and it would tip off the client of a function that the parameter in would never
be altered in any way.

Richard 




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
       [not found]                             ` <37e2e58c@news1.prserv.net>
@ 1999-09-22  0:00                               ` Richard D Riehle
  1999-09-22  0:00                                 ` Mark Lundquist
  1999-09-22  0:00                                 ` Matthew Heaney
  0 siblings, 2 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-22  0:00 UTC (permalink / raw)


In article <37e2e58c@news1.prserv.net>,
	"Matthew Heaney" <matthew_heaney@acm.org> wrote:

>Let me preface this discussion by saying that I'm advocating that internal
>state changes be allowed only for limited (private), by-reference types.
>Of course, internally, there are some state changes, but the client doesn't
>know or care about them.  That's because the postcondition is
>
>  function Get_Attr (O : T) return Attr_T;
>  --
>  -- Postcondition: return current value of Attr.
>
>and the postcondition is in fact satisfied.  Whether some internal state
>changes are made in order to satisfy the postcondition is irrelevant.
>
>If you don't want internal state changes to occur as a result of invoking
>Get_Attr, then how do you state that as a postcondition?

Ada does not support post-conditions.  I am not persuaded that a comment will
have any effect on a client of a design.  

>> I do subscribe to the idea of ensuring that the client of a query is
>> guaranteed that the query will not have side-effects.  That, to my mind, is
>> not extreme.
>
>It's not extreme, it's just wrong.

We will have to agree to disagree on this.  It is a simple proposition.  Permit
a designer to designate an access parameter to be constant.  The client has a
guarantee there will be no change to the incoming data.  I am not sure why this
is so difficult.  We would be taking away nothing in flexibility and adding something
in terms of the contract.  

>The sine qua non of the object paradigm is that we don't describe an object
>in terms of its representation.  We describe the object in terms of what
>things you can do to it.

No disagreement here. And we describe the the things we can to the object in
the form of a contract.  The better the contract describes what is legal, what
to expect, the better the client understands what to expect of it.

>You seem to be saying:
>
>  Query the object, without changing its state.
>
>But what does that statement really mean?  A client doesn't know anything
>about an object's state -- he only knows about what he can do to the object
>(here, select a value).

The client knows what to expect of a contract by what is revealed.  Also, the
designer of the original function can specify, long before the algorithms for
the function are written, the contractual constraints for that function.  This
could even be useful at the level where a function refers to an abstract class
and sets the standard for all derivations and overriding of that function for
that class.  

>How would you even write a postcondition that says "internal state of object
>hasn't changed"?  You're making a statement about internal behavior, in a
>postcondition that describes external behavior.

There are no postconditions in Ada, as mentioned earlier.  Instead of a post-
condition, we can guarantee the immutability of the data, in the specification of
the subprogram, by making an access parameter constant.  

>The other issue is, how should a client use this information?  How does
>knowing that a selector function returns a value without changing internal
>state benefit the client?

The information is useful at many different levels.  Not the least of those is
the original specification a function before the code is implemented.  As to 
the client, knowing that an access parameter to an integer or a floating point
value (as an example) is not modified in the function can be a useful thing. Not
every access value is a limited type.

>(And remember, I'm only talking about internal state changes to limited
>private, by-reference types.  Objects that are limited are always variables,
>never constants.)

I am actually not objecting to you notion regarding limited private, by-reference
types.   

>Consider an analogy: people who believe in ESP.  When you confront them with
>studies that indicate no testing success beyond what's predicted using
>probability theory, they say "Well, ESP only works sometimes, and it's hard
>to tell when."

I am not sure what this means in this discussion.  I am certainly not suggesting
anything remotely approaching ESP.  On the contrary, I am advocating a contract that
is a little more explicit vis a vis mutability of access parameters.

>OK, fine, but then what would the world look like if there weren't ESP?  If
>an ESP world looks just like a non-ESP world, then what's the difference?
>Why include ESP in the model at all?  Just use Occam's Razor to cut ESP from
>the model, to keep the description parsimonious.
>
>What is the difference in the client's world, between invoking
>
>  constant function Get_Attr (O : in T) return Attr_T;
>
>and invoking
>
>  function Get_Attr (O : in T) return Attr_T;

For an in mode parameter, there is no problem and no need for the constant
designation. The function that raises a potential problem is one with the
specification:
 
      function Get_Attr(O : access T) return Attr_T;

>As far as I can tell, these worlds look exactly the same.

Yes, Matt, yours look exactly the same. But they do not look like mine.

Someone else commented on the quest for purity.  That is not my quest. Mine is
simple and not difficult.   Simply, it would be nice to have a way to sometimes
guarantee in a function specification that an implementation of that function
would not modify the value of an access parameter.  Another correspondent noted
that const is required in C++ to offset a language problem.   We are not talking
here of C++.  We are all agreed that the problem of modifying an access value
can occur in Ada.  We simply do not agree that it is worth closing the loophole
created by this feature.

Richard Riehle
 




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                               ` Richard D Riehle
  1999-09-22  0:00                                 ` Mark Lundquist
@ 1999-09-22  0:00                                 ` Matthew Heaney
  1999-09-22  0:00                                   ` Richard D Riehle
  1 sibling, 1 reply; 69+ messages in thread
From: Matthew Heaney @ 1999-09-22  0:00 UTC (permalink / raw)


In article <7s9nd0$cbe@dfw-ixnews17.ix.netcom.com> , Richard D Riehle 
<LaoXhai@ix.netcom.com>  wrote:

> Ada does not support post-conditions.  I am not persuaded that a comment will
> have any effect on a client of a design.

Every operation has a precondition and a postcondition, irrespective of
whether of not it is expressed in the language proper.

For example:

  procedure Push
    (Item  : in     Item_Type;
     Stack : in out Stack_Type);
  --
  -- Precondition :
  --    not Is_Full (Stack)
  --
  -- Postcondition :
  --
  -- Get_Top (Stack) = Item
  -- Depth (Stack) = Depth (old Stack) + 1


If operations don't have postconditions, then what does invoking an
operation mean?


> We will have to agree to disagree on this.  It is a simple proposition.
> Permit a designer to designate an access parameter to be constant.  The client
> has a guarantee there will be no change to the incoming data.  I am not sure
> why this is so difficult.  We would be taking away nothing in flexibility and
> adding something in terms of the contract.

I think we're in violent agreement.

For non-private types, I think we can all agree that letting the caller know
there will be no state changes is A Good Idea.  Here it's easy to specify a
postcondition that means "no state change," because the state is a public
part of the object.

However, for private types, there is no such thing as "public state," so
there is obvious difficulty in specifying a postcondition that means "no
state change."


>>How would you even write a postcondition that says "internal state of object
>>hasn't changed"?  You're making a statement about internal behavior, in a
>>postcondition that describes external behavior.
>
> There are no postconditions in Ada, as mentioned earlier.

Disagree.  There are postconditions, it's just that they aren't expressible
in the language proper.


> Instead of a post- condition, we can guarantee the immutability of the data,
> in the specification of the subprogram, by making an access parameter
> constant.

I think we agree that for non-private types, this is a good idea.


>>(And remember, I'm only talking about internal state changes to limited
>>private, by-reference types.  Objects that are limited are always variables,
>>never constants.)
>
> I am actually not objecting to you notion regarding limited private,
> by-reference types.

Again, we seem to be in agreement.


> We are all agreed that the problem of modifying an access value can occur in
> Ada.  We simply do not agree that it is worth closing the loophole created by
> this feature.

I think we do agree that it is worth closing this loophole.

Matt
--
Help keep evolution in the science classroom and religion out: become a
member of the National Center for Science Education.

<http://www.natcenscied.org/>




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                               ` Richard D Riehle
@ 1999-09-22  0:00                                 ` Mark Lundquist
  1999-09-22  0:00                                   ` Mark Lundquist
  1999-09-22  0:00                                 ` Matthew Heaney
  1 sibling, 1 reply; 69+ messages in thread
From: Mark Lundquist @ 1999-09-22  0:00 UTC (permalink / raw)


I've been trying to clarify things here, but it feels like I'm trying to put out a fire
with gasoline!  Why isn't it working?  :-) :-)

Richard D Riehle wrote:

> >> I do subscribe to the idea of ensuring that the client of a query is
> >> guaranteed that the query will not have side-effects.  That, to my mind, is
> >> not extreme.
> >
> >It's not extreme, it's just wrong.
>
> We will have to agree to disagree on this.  It is a simple proposition.  Permit
> a designer to designate an access parameter to be constant.

You mean, permit the object designated by a formal access parameter to be constant,
correct?  (Formal access parameters are already constant).  If that is all you mean,
then it's precisely what Matt proposed, so whatever you're agreeing to disagree on, it
isn't this.

>  The client has a
> guarantee there will be no change to the incoming data.

Unless you're proposing something more than just "access constant" parameters, it has no
such guarantee, in view of unchecked programming and also the "Rosen Trick"
(respectively, the crude and the elegant forms of what I've been calling "covert
modification").

>  I am not sure why this
> is so difficult.

It's difficult for two reasons.  First, because you keep on adding the excess baggage
language about side-effects and guarantees and so forth.  If all you mean is "constant",
then just stop there while the meaning is clear!  You say "all I want is X, why is that
so difficult", and then you add something that X doesn't entail.  Secondly, if you do
want to preclude covert modification, then it's not clear what it especially has to do
with access parameters -- don't you care about the same thing for normal "in"
parameters, and if so what do you propose to do about them?

> We would be taking away nothing in flexibility and adding something
> in terms of the contract.

True if you just mean "access constant" parameters.  If in addition you mean to preclude
covert modification (implied: for limited private types) then the opposite is true: we
would actually be taking away from flexibility (in the implementation of the subprogram)
and adding no value to the contract (since the object type is limited private).

> There are no postconditions in Ada, as mentioned earlier.  Instead of a post-
> condition, we can guarantee the immutability of the data, in the specification of
> the subprogram, by making an access parameter constant.

Making the designated object constant (the parameter itself already is).  Once again, if
all you mean is "constant", then don't add the incorrect "immutability" verbiage,
everyone knows what constant means and there is no disagreement!  OTOH if you really
mean the "immutability stuff, then there is disagreement, and you also shouldn't claim
that all you want is to have access-to-constant parameters.

>
>
> >The other issue is, how should a client use this information?  How does
> >knowing that a selector function returns a value without changing internal
> >state benefit the client?
>
> The information is useful at many different levels.  Not the least of those is
> the original specification a function before the code is implemented.  As to
> the client, knowing that an access parameter to an integer or a floating point
> value (as an example) is not modified in the function can be a useful thing.

Agreed.

> Not
> every access value is a limited type.

True.

>
>
> >(And remember, I'm only talking about internal state changes to limited
> >private, by-reference types.  Objects that are limited are always variables,
> >never constants.)
>
> I am actually not objecting to you notion regarding limited private, by-reference
> types.

So there's hope!

>
>
> >Consider an analogy: people who believe in ESP.  When you confront them with
> >studies that indicate no testing success beyond what's predicted using
> >probability theory, they say "Well, ESP only works sometimes, and it's hard
> >to tell when."
>
> I am not sure what this means in this discussion.  I am certainly not suggesting
> anything remotely approaching ESP.

<whew!>...   :-) :-)

> Another correspondent noted
> that const is required in C++ to offset a language problem.

That would be me... :-)

> We are not talking
> here of C++.

No, but if the idea of a "constant function" was conceived by analogy to C++'s "const
member function", then it was fair to discuss why they are required in C++ as part of
the explanation for why they are not needed in Ada.

> We are all agreed that the problem of modifying an access value
> can occur in Ada.

Yes (but note, the actual cannot be a constant view [RM 3.10.2(25)]).

>  We simply do not agree that it is worth closing the loophole
> created by this feature.
>

Two points:

1)  The access-to-constant parameter proposal is what you at times have been saying is
the "simple" thing that it's "all you're asking for".  If that's really true, then
nobody is disagreeing with you.

2) The real loophole is created by unchecked programming, and also by the "Rosen
Trick".  But that has nothing to do with access parameters.

> Richard Riehle

BTW -- I've enjoyed and learned from your articles and posts over the years, so it's
with the utmost respect that I'm disagreeing, or agreeing, or whatever the heck it turns
out to have been... :-) :-)

--

Mark Lundquist
Senior Software Engineer
Rational Software
Development Solutions Business Unit
UNIX Suites Group
Aloha, OR, USA







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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                 ` Mark Lundquist
@ 1999-09-22  0:00                                   ` Mark Lundquist
  0 siblings, 0 replies; 69+ messages in thread
From: Mark Lundquist @ 1999-09-22  0:00 UTC (permalink / raw)


My post must have been too long, because I got sloppy at the end.  There's something about
reading my posts after it's too late to change them, that helps me see where I goofed up...
:-)

Mark Lundquist (c'est moi) wrote:

> >  We simply do not agree that it is worth closing the loophole
> > created by this feature.
> >
>
> Two points:
>
> 1)  The access-to-constant parameter proposal is what you at times have been saying is
> the "simple" thing that it's "all you're asking for".  If that's really true, then
> nobody is disagreeing with you.
>
> 2) The real loophole is created by unchecked programming, and also by the "Rosen
> Trick".  But that has nothing to do with access parameters.
>

It's implied by (1), but I ought to say it explicitly :  I do agree with you that not
having access-to-constant parameters is a bit of a loophole and that it's worth closing.

As for (2), the Rosen Trick is only a loophole in the case of non-private types, and I also
agree that loophole should be closed (whether in the case of access parameters or not).

--

Mark Lundquist
Senior Software Engineer
Rational Software
Development Solutions Business Unit
UNIX Suites Group
Aloha, OR, USA







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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                   ` Richard D Riehle
  1999-09-22  0:00                                     ` Matthew Heaney
@ 1999-09-22  0:00                                     ` Matthew Heaney
  1999-09-23  0:00                                       ` Vincent Marciante
                                                         ` (3 more replies)
  1999-09-23  0:00                                     ` Robert Dewar
  2 siblings, 4 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-22  0:00 UTC (permalink / raw)


In article <7sas3p$bfa@dfw-ixnews3.ix.netcom.com> , Richard D Riehle 
<LaoXhai@ix.netcom.com>  wrote:

>>If operations don't have postconditions, then what does invoking an
>>operation mean?
>
> The question is, what does invoking an operation mean to the caller.

No.  The supplier defines what invoking an operation means.  The supplier
states this, explicitly or not, in the form of a postcondition.


> It is not easy to specify a post-condition.  The post-condition is implied,
> and becomes a client's best guess at your intention.

If this is the case, then clearly there is a problem.  There should be no
ambiguity about the meaning of an operation.


> If you could specify a post-condition for the function such as, (pseudocode),
>
>        Ensure(X before call = X after call);
>
> or even
>
>        Invariant(X always = X before call);
>
> the client would have assurance of the stability of X.

1) For non-private types, this is only an issue for access parameters.  We
both agree that we should be able to pass parameters as "access constant T",
in order to indicate to the client that no state change will occur.  (If you
don't need an access parameter, then just pass the parameter as in-mode.)

2) For private types, I say the "stability of X" is a meaningless statement.
A supplier's only obligation is to satisfy the postcondition, which has
nothing to say about internal state changes.  This is essentially where we
disagree (see below).


> This is not part of the Ada language, for good or bad.   Instead, we have the
> more conservative approach of range constraints, parameter modes, etc.  One of
> those parameter modes makes a parameter vulnerable to internal modification.

Yes, but this is only an issue for non-private types passed as an access
parameter.  An we agree that we would like to close this loophole by being
able to pass parameters as "access constant T".

For private types, the supplier is (or should be) free to make internal
modifications, to the extent that the postcondition is satisfied.  This is
where we disagree.


> Although there is no public state, a primitive operation with an access
> parameter can change the internal state of a parameter.  I think the guarantee
> of immutability is important for both private and non-private data.

Agree for non-private data.  Disagree for private data.


> Consider the following abstract class,
>
>       package Abstract_Level is
>           type Abstract_Declaration is abstract tagged private;
>           procedure X ( . . .) is abstract;
>           procedure Y ( . . .) is abstract;
>           function  F (A : access Abstract_Declaration) return some-type
>                                      is abstract;
>       private
>           type Abstract_Declaration is abstract tagged private;
>       end Abstract_Level;
>
> Now, anyone overriding function F can do so with implementing code that
> changes the internal state of the access parameter.

So what?  Suppose an internal state change is necessary in order to satisfy
the postcondition?  (This would still be true even if parameter A were
declared as "access constant Abstract_Declaration".)


> If, on the other hand, we were able to code the parameter so it would be a
> constant access,
>
>    function  F (A : access constant Abstract_Declaration) return some-type
>                                      is abstract;
>
> every overriding would be forced to leave the data in the parameter unchanged.

You seem to want to put a constraint on the supplier.  Why?

The type system is in place to prevent the client from breaking an
abstraction.  It is not in place to tie the supplier's hands behind his
back, so that he can be prevented from making internal state changes (to an
abstraction implemented as a private type).

The language should get out of the supplier's way, and let him do whatever
is necessary in order to implement an abstraction.

It doesn't make any difference to a client (of a private-type abstraction)
whether the data is changed or unchanged.  A client's only interest is in
whether the postcondition is satisfied, and state changes are not part of
the postcondition.



> Once again, what is our disagreement.  You just agreed with me on the very
> essence of my main point.  I am confused about where it is we don't agree.

We agree that the language should be amended to be able to pass parameters
as "access constant T" instead of just "access T", where T is any kind of
type.

We disagree about when an implementor of a private-type abstraction should
be allowed to make internal state changes.

I say the implementor of a private-type abstraction should be able to make
internal state changes, irrespective of the parameter mode.  Even if the
language were amended to pass access parameters as "access constant T", then
I still would want to be able to make internal state changes.

You say the implementor of a private-type abstraction should obey the
parameter modes, and only be able to change state when the parameter mode is
in-out mode or "access T" mode.  When the parameter mode is in-mode or
"access constant T" mode, then the supplier should not make internal state
changes.


I think the source of this disagreement stems from a couple of things:

1) Whether there are really postconditions in Ada (really, any language
other the Eiffel or Larch or ???).

I say yes, there are postconditions, even if they aren't officially
specified directly in the language.  You say no.


2) Whether an internal state change is part of a postcondition.

I say that for a private type, any statement about an "internal state
change" as part of a postcondition is meaningless, because a postcondition
only says what's true externally.

Even though you don't seem to recognize postconditions officially, you do
regard internal state changes as part of the defined, external behavior of a
private-type abstraction.

I don't regard internal state changes as part of the external behavior.


--
It is impossible to feel great confidence in a negative theory which has
always rested its main support on the weak points of its opponent.

Joseph Needham, "A Mechanistic Criticism of Vitalism"




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                   ` Richard D Riehle
@ 1999-09-22  0:00                                     ` Matthew Heaney
  1999-09-22  0:00                                     ` Matthew Heaney
  1999-09-23  0:00                                     ` Robert Dewar
  2 siblings, 0 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-22  0:00 UTC (permalink / raw)


In article <7sas3p$bfa@dfw-ixnews3.ix.netcom.com> , Richard D Riehle 
<LaoXhai@ix.netcom.com>  wrote:

>>If operations don't have postconditions, then what does invoking an
>>operation mean?
>
> The question is, what does invoking an operation mean to the caller.

No.  The supplier defines what invoking an operation means.  The supplier
states this, explicitly or not, in the form of a postcondition.


> It is not easy to specify a post-condition.  The post-condition is implied,
> and becomes a client's best guess at your intention.

If this is the case, then clearly there is a problem.  There should be no
ambiguity about the meaning of an operation.


> If you could specify a post-condition for the function such as, (pseudocode),
>
>        Ensure(X before call = X after call);
>
> or even
>
>        Invariant(X always = X before call);
>
> the client would have assurance of the stability of X.

1) For non-private types, this is only an issue for access parameters.  We
both agree that we should be able to pass parameters as "access constant T",
in order to indicate to the client that no state change will occur.  (If you
don't need an access parameter, then just pass the parameter as in-mode.)

2) For private types, I say the "stability of X" is a meaningless statement.
A supplier's only obligation is to satisfy the postcondition, which has
nothing to say about internal state changes.  This is essentially where we
disagree (see below).


> This is not part of the Ada language, for good or bad.   Instead, we have the
> more conservative approach of range constraints, parameter modes, etc.  One of
> those parameter modes makes a parameter vulnerable to internal modification.

Yes, but this is only an issue for non-private types passed as an access
parameter.  An we agree that we would like to close this loophole by being
able to pass parameters as "access constant T".

For private types, the supplier is (or should be) free to make internal
modifications, to the extent that the postcondition is satisfied.  This is
where we disagree.


> Although there is no public state, a primitive operation with an access
> parameter can change the internal state of a parameter.  I think the guarantee
> of immutability is important for both private and non-private data.

Agree for non-private data.  Disagree for private data.


> Consider the following abstract class,
>
>       package Abstract_Level is
>           type Abstract_Declaration is abstract tagged private;
>           procedure X ( . . .) is abstract;
>           procedure Y ( . . .) is abstract;
>           function  F (A : access Abstract_Declaration) return some-type
>                                      is abstract;
>       private
>           type Abstract_Declaration is abstract tagged private;
>       end Abstract_Level;
>
> Now, anyone overriding function F can do so with implementing code that
> changes the internal state of the access parameter.

So what?  Suppose an internal state change is necessary in order to satisfy
the postcondition?  (This would still be true even if parameter A were
declared as "access constant Abstract_Declaration".)


> If, on the other hand, we were able to code the parameter so it would be a
> constant access,
>
>    function  F (A : access constant Abstract_Declaration) return some-type
>                                      is abstract;
>
> every overriding would be forced to leave the data in the parameter unchanged.

You seem to want to put a constraint on the supplier.  Why?

The type system is in place to prevent the client from breaking an
abstraction.  It is not in place to tie the supplier's hands behind his
back, so that he can be prevented from making internal state changes (to an
abstraction implemented as a private type).

The language should get out of the supplier's way, and let him do whatever
is necessary in order to implement an abstraction.

It doesn't make any difference to a client (of a private-type abstraction)
whether the data is changed or unchanged.  A client's only interest is in
whether the postcondition is satisfied, and state changes are not part of
the postcondition.



> Once again, what is our disagreement.  You just agreed with me on the very
> essence of my main point.  I am confused about where it is we don't agree.

We agree that the language should be amended to be able to pass parameters
as "access constant T" instead of just "access T", where T is any kind of
type.

We disagree about when an implementor of a private-type abstraction should
be allowed to make internal state changes.

I say the implementor of a private-type abstraction should be able to make
internal state changes, irrespective of the parameter mode.  Even if the
language were amended to pass access parameters as "access constant T", then
I still would want to be able to make internal state changes.

You say the implementor of a private-type abstraction should obey the
parameter modes, and only be able to change state when the parameter mode is
in-out mode or "access T" mode.  When the parameter mode is in-mode or
"access constant T" mode, then the supplier should not make internal state
changes.


I think the source of this disagreement stems from a couple of things:

1) Whether there are really postconditions in Ada (really, any language
other the Eiffel or Larch or ???).

I say yes, there are postconditions, even if they aren't officially
specified directly in the language.  You say no.


2) Whether an internal state change is part of a postcondition.

I say that for a private type, any statement about an "internal state
change" as part of a postcondition is meaningless, because a postcondition
only says what's true externally.

Even though you don't seem to recognize postconditions officially, you do
regard internal state changes as part of the defined, external behavior of a
private-type abstraction.

I don't regard internal state changes as part of the external behavior.


--
It is impossible to feel great confidence in a negative theory which has
always rested its main support on the weak points of its opponent.

Joseph Needham, "A Mechanistic Criticism of Vitalism"




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                 ` Matthew Heaney
@ 1999-09-22  0:00                                   ` Richard D Riehle
  1999-09-22  0:00                                     ` Matthew Heaney
                                                       ` (2 more replies)
  0 siblings, 3 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-22  0:00 UTC (permalink / raw)


In article <37e8e067@news1.prserv.net>,
	"Matthew Heaney" <matthew_heaney@acm.org> wrote:

>In article <7s9nd0$cbe@dfw-ixnews17.ix.netcom.com> , Richard D Riehle 
><LaoXhai@ix.netcom.com>  wrote:
>
>> Ada does not support post-conditions.  I am not persuaded that a comment will
>> have any effect on a client of a design.
>
>Every operation has a precondition and a postcondition, irrespective of
>whether of not it is expressed in the language proper.
>
>For example:
>
>  procedure Push
>    (Item  : in     Item_Type;
>     Stack : in out Stack_Type);
>  --
>  -- Precondition :
>  --    not Is_Full (Stack)
>  --
>  -- Postcondition :
>  --
>  -- Get_Top (Stack) = Item
>  -- Depth (Stack) = Depth (old Stack) + 1
>
>
>If operations don't have postconditions, then what does invoking an
>operation mean?

The question is, what does invoking an operation mean to the caller.  If the
caller has no idea of what the pre-conditions and post-conditions (and invariants)
might be, then part of the actual meaning is hidden.  If pre-conditions were part of
the specification for each operation, the meaning would be more explicit.  
>
>I think we're in violent agreement.
>
>For non-private types, I think we can all agree that letting the caller know
>there will be no state changes is A Good Idea.  Here it's easy to specify a
>postcondition that means "no state change," because the state is a public
>part of the object.

Not too violent, I hope. It is not easy to specify a post-condition.  
The post-condition is implied, and becomes a client's best guess at your intention.
If you could specify a post-condition for the function such as, (pseudocode),

       Ensure(X before call = X after call);

or even

       Invariant(X always = X before call);

the client would have assurance of the stability of X.  This is not part of the
Ada language, for good or bad.   Instead, we have the more conservative approach of
range constraints, parameter modes, etc.  One of those parameter modes makes a
parameter vulnerable to internal modification.  

>However, for private types, there is no such thing as "public state," so
>there is obvious difficulty in specifying a postcondition that means "no
>state change."

Although there is no public state, a primitive operation with an access
parameter can change the internal state of a parameter.  I think the guarantee
of immutability is important for both private and non-private data.

>> Instead of a post- condition, we can guarantee the immutability of the data,
>> in the specification of the subprogram, by making an access parameter
>> constant.
>
>I think we agree that for non-private types, this is a good idea.

Interesting.  I thought you disagreed.  What are we arguing about anyway?
>
>>>(And remember, I'm only talking about internal state changes to limited
>>>private, by-reference types.  Objects that are limited are always variables,
>>>never constants.)

Ah. Here seems a point of difference.  Consider the following abstract class,

      package Abstract_Level is
          type Abstract_Declaration is abstract tagged private;
          procedure X ( . . .) is abstract;
          procedure Y ( . . .) is abstract;
          function  F (A : access Abstract_Declaration) return some-type
                                     is abstract;
      private
          type Abstract_Declaration is abstract tagged private;
      end Abstract_Level;

Now, anyone overriding function F can do so with implementing code that changes
the internal state of the access parameter.  If, on the other hand, we were able
to code the parameter so it would be a constant access, 

   function  F (A : access constant Abstract_Declaration) return some-type
                                     is abstract;

every overriding would be forced to leave the data in the parameter unchanged.  

Matt, I wrote the following and you replied in agreement with it.  

>> We are all agreed that the problem of modifying an access value can occur in
>> Ada.  We simply do not agree that it is worth closing the loophole created by
>> this feature.
>
>I think we do agree that it is worth closing this loophole.

Once again, what is our disagreement.  You just agreed with me on the very essence
of my main point.  I am confused about where it is we don't agree.  

Richard Riehle




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

* Re: Array of Variant Records Question...
       [not found]                     ` <wccd7viiv59.fsf@world.std.com>
       [not found]                       ` <7rrmqd$l89@drn.newsguy.com>
@ 1999-09-22  0:00                       ` Robert I. Eachus
  1 sibling, 0 replies; 69+ messages in thread
From: Robert I. Eachus @ 1999-09-22  0:00 UTC (permalink / raw)




Robert A Duff wrote:

> I understand that you can have different representations of the same
> abstract value, but that's not the case with Random -- if I call Random
> twice in a row, I get two different answers (two different abstract
> values).  I had better, or it's broken!

    Minor comment--I don't think that Bob Duff meant to mislead anyone,
but a
random number generator that never returns the same value twice in a row
is broken, just as is one that always returns the same value.  (Think
about a generator that returns boolean values.)  In any case though, the
state of the generator must change or it is broken.  (And any good
generator should not allow "weak seeds" to be used when resetting the
generator.)
-- 

                                        Robert I. Eachus

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




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

* Re: Array of Variant Records Question...
       [not found]                         ` <wcciu59n2uf.fsf@world.std.com>
@ 1999-09-22  0:00                           ` Robert I. Eachus
  1999-09-23  0:00                             ` Robert Dewar
  0 siblings, 1 reply; 69+ messages in thread
From: Robert I. Eachus @ 1999-09-22  0:00 UTC (permalink / raw)


Robert A Duff wrote:
 
> I don't know much about the theory of these things, but I was under the
> impression that Random can never ever return the same value twice in a
> row.  Robert Eachus or somebody can tell us for sure.

   See previous post.  There is a major distiction here between a
floating-point generator and an integer or fixed-point generator.  In an
idealized enivronment, a floating-point generator would have zero chance
of
returning the same value twice in a row.  (There are aleph-one possible
return values and any generator can only return aleph-null of them. 
Therefore the probabilty of returning the same value the next time it is
called is one over aleph-one.)  But in a computer environment where
floating point values are represented by a finite set of values, there
should be a small but finite probability that two succesive values are
the same.

   In the fixed-point or integer case, the number of possible return
values is very small, so that the probability of repeated values in a
long sequence approaches unity.  (Even in a boolean generator, if it is
truly random, there is a finite probability that you will see a long
sequence of True, False, True, False, True, etc...)
> 
> I do know that in fact the Random function is *not* random.
 
    (Okay, you asked.) Which Random function?  How do you know that? 
Linear Congruential Generators have a lot of faults, including that it
is possible to look at a short sequence and predict the next value.  Or
to put it differently successive  values are highly correlated.  In
fact, if you look at the unscaled output of an LCG you will never see
the same value repeated until the generator runs through its entire
period.

    The generator used by GNAT is much different.  You can only tell it
is not random by knowing its period, either by running the generator
that long, looking at interior details, or by being a very good
cryptographer.  If the generator does not behave that way, there is a
bug in the code.  (And there was a minor bug in the 3.10p code for the
integer generator...)  Pseudo-random number generators of this type are
technically "more random than random," and are used to "whiten" the
outpot of physical generators that sample the environment.
-- 

                                        Robert I. Eachus

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




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                   ` Richard D Riehle
  1999-09-22  0:00                                     ` Matthew Heaney
  1999-09-22  0:00                                     ` Matthew Heaney
@ 1999-09-23  0:00                                     ` Robert Dewar
  1999-09-27  0:00                                       ` Richard D Riehle
  2 siblings, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-23  0:00 UTC (permalink / raw)


In article <7sas3p$bfa@dfw-ixnews3.ix.netcom.com>,
  Richard D Riehle <LaoXhai@ix.netcom.com> wrote:
> The question is, what does invoking an operation mean to the
caller.

The answer is that without comments, the caller has not the
foggiest idea. Specifications in Ada give only the bearest
structural details on how to call a subprogram, they do not
give any hint as to what the subprogram is supposed to do!

So let's not get too excercised about what is and what is not
in the actual syntax, since we know that the most critical part
in any case will be in the comments saying what is to be done.

Richard, if you think the client and the implementor will ignore
the comments you are completely lost in any case, since these
comments are the *only* clue as to the functionality to be used
or implemented.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Array of Variant Records Question...
  1999-09-22  0:00                           ` Array of Variant Records Question Robert I. Eachus
@ 1999-09-23  0:00                             ` Robert Dewar
  1999-09-23  0:00                               ` Robert I. Eachus
  0 siblings, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-23  0:00 UTC (permalink / raw)


In article <37E922DE.9007776F@mitre.org>,
  "Robert I. Eachus" <eachus@mitre.org> wrote:
> Robert A Duff wrote:
>
> > I don't know much about the theory of these things, but I
was under the
> > impression that Random can never ever return the same value
twice in a
> > row.  Robert Eachus or somebody can tell us for sure.
>
>    See previous post.  There is a major distiction here
between a
> floating-point generator and an integer or fixed-point
generator.  In an
> idealized enivronment, a floating-point generator would have
zero chance
> of
> returning the same value twice in a row.

You mean "real" instead of "floating-point", please do not use
floating-point to mean the real numbers of mathematics, they
are quite different. The term floating-point should be reserved
to computer number systems, which are not in any sense
non-ideal. They have well defined semantics which just happen
to be different from those of real arithmetic.

Since we never have real arithmetic on computers, talking about
this case is a red herring that has nothing to do with anything
we are interested in here.


> But in a computer environment where
> floating point values are represented by a finite set of
values, there
> should be a small but finite probability that two succesive
values are
> the same.

Yes, and that is what is important, and to say it again, there
is nothing "non-ideal" about this situation. Thinking of
computer floating-point as a non-ideal approximation of
real arithmetic is helpful only at a very simple level of
abstraction, and is not useful for serious numeric work.



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                     ` Matthew Heaney
@ 1999-09-23  0:00                                       ` Vincent Marciante
  1999-09-23  0:00                                         ` Matthew Heaney
  1999-09-24  0:00                                       ` Robert A Duff
                                                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 69+ messages in thread
From: Vincent Marciante @ 1999-09-23  0:00 UTC (permalink / raw)


Matthew Heaney wrote:
>  
> We agree that the language should be amended to be able to pass parameters
> as "access constant T" instead of just "access T", where T is any kind of
> type.
> 

Would the following (or similar) also require consideration? 
Doesn't it also exhibit a loophole?  If not, why not?


...

type scalar is new integer
type scalar_reference is access all scalar;


type composite is 
  record
    sca : scalar;
    ref : scalar_reference; 
  end record;
type composite_reference is access composite;


type composite_node is 
  record
    ref1 : scalar_reference; 
    ref2 : composite_reference; 
  end record;

...

function inc_formal_ref1_object (formal : composite_node) 
                                 return   boolean is
begin
  formal.ref1.all := scalar'succ(formal.ref1.all);
  return true;
exception
  when others => return false;
end; 


function inc_formal_ref2_ref_object (formal : composite_node) 
                                     return   boolean is
begin
  formal.ref1.ref.all := scalar'succ(formal.ref1.ref.all);
  return true;
exception
  when others => return false;
end; 




-- 
To reply, please remove the four and five 
from the anti-spammed address that is shown.




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-23  0:00                                       ` Vincent Marciante
@ 1999-09-23  0:00                                         ` Matthew Heaney
  0 siblings, 0 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-23  0:00 UTC (permalink / raw)


In article <37E9B259.7C58@l5i.net> , Vincent Marciante <ma4rciant@l5i.net>
wrote:

> Would the following (or similar) also require consideration?
> Doesn't it also exhibit a loophole?  If not, why not?

We were only talking about state changes that violate the terms of the
contract between client and supplier (although Richard and I do not agree on
the exact nature of that contract).

Your example illustrates the point I was trying to make: the postcondition
is "formal.ref1.all = old formal.ref1.all + 1", and the subprogram does
indeed satisfy that postcondition.  Here, the state is completely public,
but no illicit state changes have taken place other that what were promised.

I suppose if you wanted to be completely doctrinaire you could pass Formal
as an in-out mode parameter, but I don't recommend this.  It's no secret
that Formal is a record the contains access objects, and that the function
inc_formal_ref1_object modifies the value designated by the access object,
not the access object itself.  So just pass Formal as in-mode.

Your function does exactly what it promised to do: nothing more, and nothing
less.  So as far as I am concerned, there is no problem with it.

--
Those who believe in the supernatural should be required to learn computer
programming.  This would force them to discover that things which appear to
be completely mysterious and incomprehensible, in fact have a logical, and
usually simple, explanation.

J. B. R. Yant, Mortal Words




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

* Re: Array of Variant Records Question...
  1999-09-23  0:00                             ` Robert Dewar
@ 1999-09-23  0:00                               ` Robert I. Eachus
  0 siblings, 0 replies; 69+ messages in thread
From: Robert I. Eachus @ 1999-09-23  0:00 UTC (permalink / raw)


Robert Dewar wrote:
  
> You mean "real" instead of "floating-point", please do not use
> floating-point to mean the real numbers of mathematics, they
> are quite different. The term floating-point should be reserved
> to computer number systems, which are not in any sense
> non-ideal. They have well defined semantics which just happen
> to be different from those of real arithmetic.
  
> Since we never have real arithmetic on computers, talking about
> this case is a red herring that has nothing to do with anything
> we are interested in here.
 
    Hmmm.  This is only about terminology, and I'll have to stick with
mine in this case.  There are "real" random generators, but that term is
usually
reserved for analog devices which output a voltage signal.  Quite
popular in
white noise generators.  As for the number model you are quite correct
that there is a major difference between real numbers and floating-point
numbers.  It is just that I was talking about RNGs not numbers.

-- 

                                        Robert I. Eachus

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




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                     ` Matthew Heaney
  1999-09-23  0:00                                       ` Vincent Marciante
@ 1999-09-24  0:00                                       ` Robert A Duff
  1999-09-25  0:00                                         ` Matthew Heaney
  1999-09-27  0:00                                       ` Richard D Riehle
  1999-09-27  0:00                                       ` Richard D Riehle
  3 siblings, 1 reply; 69+ messages in thread
From: Robert A Duff @ 1999-09-24  0:00 UTC (permalink / raw)


"Matthew Heaney" <matthew_heaney@acm.org> writes:

> 2) For private types, I say the "stability of X" is a meaningless statement.
> A supplier's only obligation is to satisfy the postcondition, which has
> nothing to say about internal state changes.

Please define exactly what you mean by "internal" state change.
How can one tell the difference between internal and external
state changes?

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




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-24  0:00                                       ` Robert A Duff
@ 1999-09-25  0:00                                         ` Matthew Heaney
  0 siblings, 0 replies; 69+ messages in thread
From: Matthew Heaney @ 1999-09-25  0:00 UTC (permalink / raw)


In article <wcchfkk2ocx.fsf@world.std.com> , Robert A Duff 
<bobduff@world.std.com>  wrote:

> "Matthew Heaney" <matthew_heaney@acm.org> writes:
>
>> 2) For private types, I say the "stability of X" is a meaningless statement.
>> A supplier's only obligation is to satisfy the postcondition, which has
>> nothing to say about internal state changes.
>
> Please define exactly what you mean by "internal" state change.

External = public state  = partial view of type
Internal = private state = full view of type

For example, in Ada.Text_IO, the type is declared as

  type File_Type is limited private;

There is no external state.  The only thing I know (publicly) about File_Type
is what operations are available for it.

You could loosely refer to selector functions like Name or Is_Open as "external
state," but I'm not doing that here.  In a postcondition, I would state what
values those functions should return, but that's not quite what I mean by
external state (it's more like external "behavior").


> How can one tell the difference between internal and external
> state changes?

For a private type, there is no such thing as "external state," so this
question goes away.

Actually, that's a bit of a lie, since I could declare a tagged type this way:

  type T_Public is
    abstract tagged limited record
      I : Integer;
    end record;

  type T is
    new T_Public with private;

Here, objects of type T have some state that's external, namely component I.
But then it's easy to say what happens to the external state (I) in the
postcondition.


--
It is impossible to feel great confidence in a negative theory which has always
rested its main support on the weak points of its opponent.

Joseph Needham, "A Mechanistic Criticism of Vitalism"




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-27  0:00                                       ` Richard D Riehle
@ 1999-09-27  0:00                                         ` David Kristola
  0 siblings, 0 replies; 69+ messages in thread
From: David Kristola @ 1999-09-27  0:00 UTC (permalink / raw)



On Sun, 26 Sep 1999 22:38:59 -0700, Richard D Riehle wrote
(in message <7so9vb$59b@dfw-ixnews19.ix.netcom.com>):
>           constant function F ( ... ) return ... 

The other form lets you mix constant and non-constant parameters:

   function F
      (Parm_1 : access constant T1;
       Parm_2 : access          T2) return R;

(Boy, this is going to mess up mode alignment.  It is neat that
"access" just happens to be as long as "in out").

What i would really like to know is; what can't i do with a
constant access parameter in the body of the function?

I would guess that i could not pass it as a parameter to another
function unless that too was "access constant".


-- 
--djk, keeper of arcane lore & trivial fluff
Home: David95037 at aol dot come
Rot13: Qnivq95037@nby.pbz
Spam: goto.hades@welovespam.com





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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                     ` Matthew Heaney
                                                         ` (2 preceding siblings ...)
  1999-09-27  0:00                                       ` Richard D Riehle
@ 1999-09-27  0:00                                       ` Richard D Riehle
  1999-09-27  0:00                                         ` David Kristola
  3 siblings, 1 reply; 69+ messages in thread
From: Richard D Riehle @ 1999-09-27  0:00 UTC (permalink / raw)


In article <37e994c0@news1.prserv.net>,
	"Matthew Heaney" <matthew_heaney@acm.org> wrote:


>For private types, the supplier is (or should be) free to make internal
>modifications, to the extent that the postcondition is satisfied.  This is
>where we disagree.

We agree, then, that a designer should be allowed to design a
contract that declares (X : access constant T) as a mode for a 
non-private type. Interesting that we both came to this notion
independently and found ourselves arguing about it.  I have, 
before this little discussion, encountered others in the Ada 
community who have also come to this idea on their own.  

>Agree for non-private data.  Disagree for private data.

Now we are focusing on the precise area of disagreement.  Once again,
we are not so far apart.  If we are to agree that the syntax, 

    function F(X : access constant T) return R;

or something like it (I am not as concerned with the syntax as the
semantics), then it would make sense to extend that capability to
all types, private and non-private.  The designer has the ability 
to overload an operation with a new primitive, though not ability to
override it.  This does introduce a complication in the overloading
rules that requires a compiler to check one additional mode level of
the parameter profile.  However, that is true with both private and
non-private types.

In my earlier example, repeated below, 

>>   package Abstract_Level is
>>     type Abstract_Declaration is abstract tagged private;
>>     procedure X ( . . .) is abstract;
>>     procedure Y ( . . .) is abstract;
>>     function  F (A : access constant Abstract_Declaration) 
                             return some-type
>>                           is abstract;
>>  private
>>    type Abstract_Declaration is abstract tagged private;
>>  end Abstract_Level;

The class designer is explicitly declaring that overriding of the 
function F prohibits modification of the data components of
Abstract_Declaration. If it becomes useful to introduce a new 
function later with different properties, no problem.  

Returning to the syntax issue for a moment, I am still not convinced 
that, in the absence of explicit pre-, post-, and invariant conditions, 
having the ability to declare a function as constant would not be a
useful feature.  In this case, the constant function would behave 
just like a protected function.  Although you, along with many others,
do not like this syntax,

          constant function F ( ... ) return ...

it would serve the purpose nicely.  Such functions would be only 
useful as queries on the state of data.  I realize that
this notion foments another storm of protest and indignation. 

Richard Riehle
richard@adaworks.com
http://www.adaworks.com






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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-22  0:00                                     ` Matthew Heaney
  1999-09-23  0:00                                       ` Vincent Marciante
  1999-09-24  0:00                                       ` Robert A Duff
@ 1999-09-27  0:00                                       ` Richard D Riehle
  1999-09-27  0:00                                       ` Richard D Riehle
  3 siblings, 0 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-27  0:00 UTC (permalink / raw)


In article <37e994c0@news1.prserv.net>,
	"Matthew Heaney" <matthew_heaney@acm.org> wrote:

>You seem to want to put a constraint on the supplier.  Why?

No, Matt.  I am not putting a constraint on the supplier.  Rather,
I am in favor of making it possible for the supplier to constrain
her/his own design to ensure behavior as intended.  Moreover, I
think the supplier should be able to explicitly state that behavior
to the client.  Even further, a designer of an abstract class should
be able to state, in a parameter list, that there is an expectation
that certain subprograms, using specified parameters, will not alter
the content of those parameters.  

>The type system is in place to prevent the client from breaking an
>abstraction.  It is not in place to tie the supplier's hands behind his
>back, so that he can be prevented from making internal state changes (to an
>abstraction implemented as a private type).

As noted my Mr. Lundquist ( the Rosen trick) and others, the type 
system is not sufficient, by itself.  This is why the type system
is supported by rules for visibility and accessibility.  The supplier
would not be constrained from making changes in to an access parameter
in a subprogram.  Rather, such changes would be proscribed in a
subprogram including a mode of access constant.  

>The language should get out of the supplier's way, and let him do whatever
>is necessary in order to implement an abstraction.

Agreed. That "whatever is necessary" should include the ability to 
declare the expectations for an abstraction.  The notion of constant
functions does not get in the way of a supplier.  Rather, it provides
a sense of security to her/his original intentions.

>It doesn't make any difference to a client (of a private-type abstraction)
>whether the data is changed or unchanged.  A client's only interest is in
>whether the postcondition is satisfied, and state changes are not part of
>the postcondition.

Of course, in Ada, there is no indication to the client of what a 
post-condition might be. A comment is not sufficient since later 
modification might override the comment.  Instead, if the original
designer declares that a function is constant, that is part of the
contract and every future modification to that constant requires 
adherence to that contract.  

The constraint is not on the original designer.  In fact, it is the
original designer who declares the constraint.  Rather, it is on the
future maintenance programmer.  

>I think the source of this disagreement stems from a couple of things:
>
>1) Whether there are really postconditions in Ada (really, any language
>other the Eiffel or Larch or ???).

I confess a certain interest in the assertion mechanisms of Eiffel, 
but these mechanisms are not unique to Eiffel.  They are widely
accepted in much of the literature of computer science.  As of now,
I consider the Ada model more appropriate to safety-critical software
for a lot of reasons.  This is not the time to enumerate these.

>I say yes, there are postconditions, even if they aren't officially
>specified directly in the language.  You say no.

Postconditions are implied in the very fact of writing a subprogram.
The problem is that they are not always clear to the client of a 
contract.  For well-known applications such as data structures (your
example of a Stack) we have a reasonable expectation of behavior. For
other applications, we have no such intuitive expectation.  

An assertion in the form of a comment can never be trusted.  One that
is checked by the compiler (or RTE) is more trusted.  As assertions
become more complex,

                  Require (X  >= Y or (Z /= w) and (Q > P)

they become unwieldy and uncheckable except through theorem provers.
We are not yet at the point in software science that we can 
consistently prove such things reliably.

>
>2) Whether an internal state change is part of a postcondition.
>
>I say that for a private type, any statement about an "internal state
>change" as part of a postcondition is meaningless, because a postcondition
>only says what's true externally.

This does fly in the opposite direction of those who believe that
postconditions should publicly state the expectations of a contract.

>Even though you don't seem to recognize postconditions officially, you do
>regard internal state changes as part of the defined, external behavior of
a
>private-type abstraction.
>
>I don't regard internal state changes as part of the external behavior.

Internal behavior reflects some expectation of an external client.  
Can the client rely on the contract.  Maintenance of internal 
behavior should reflect the rules of that contract.  A change of 
internal behavior and state that should not be overridden
at the whim of some maintenance programmer who finds it possible to 
take advantage of some side-effect at the expense of those external
expectations, at the expense of the contract.

Richard Riehle
richard@adaworks.com
http://www.adaworks.com
 




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-23  0:00                                     ` Robert Dewar
@ 1999-09-27  0:00                                       ` Richard D Riehle
  1999-09-28  0:00                                         ` Robert Dewar
  1999-09-28  0:00                                         ` Robert Dewar
  0 siblings, 2 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-27  0:00 UTC (permalink / raw)


In article <7sc6b6$c6m$1@nnrp1.deja.com>,
	Robert Dewar <robert_dewar@my-deja.com> wrote:

>The answer is that without comments, the caller has not the
>foggiest idea. Specifications in Ada give only the bearest
>structural details on how to call a subprogram, they do not
>give any hint as to what the subprogram is supposed to do!

Exactly, Robert.  In the absence of assertions that can be
checked by the compiler, comments are the only recourse. And
you and I both agree about the problems of compiler-checked
assertions.  An assertion can be more wrong than the program itself.

>So let's not get too excercised about what is and what is not
>in the actual syntax, since we know that the most critical part
>in any case will be in the comments saying what is to be done.

In the words of Ophelia, "Tis true, 'tis pity.  'Tis pity, 'tis true." *
Of course, Robert, there is not intention in quoting this to suggest
any sense of madness here.  :-)

>Richard, if you think the client and the implementor will ignore
>the comments you are completely lost in any case, since these
>comments are the *only* clue as to the functionality to be used
>or implemented.

Robert, one reason why I sometimes still look at the internal 
implemention of a subprogram is my distrust of comments over the
life of a contract.  The comment may introduce me to what the
subprogram does, but rarely tells me what it does not do.  When
a contract is new, the comments are usually pretty reliable. As
the program ages and is subjected to an increased level of 
modification, "all bets are off."   So it is, Robert, that I am
so often, as you say, "completely lost."  

Fortunately, well-designed Ada software will export services that 
do only one thing and are, as you so often emphasize, more readable
than writeable.  When looking at a C++ program, I am often "completely
lost" because there is so little hope of unraveling the meaning of
little modifications made to a program over its lifetime.  I certainly
cannot rely on the comments when using heavily maintained C++ code.

Richard Riehle
http://www.adaworks.com

        * My copy of Hamlet is not immediately handy, but
          I think I am pretty close to the original text.

                                Richard




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-27  0:00                                       ` Richard D Riehle
@ 1999-09-28  0:00                                         ` Robert Dewar
  1999-09-28  0:00                                           ` Richard D Riehle
  1999-09-28  0:00                                         ` Robert Dewar
  1 sibling, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-28  0:00 UTC (permalink / raw)


In article <7socka$6u4@dfw-ixnews19.ix.netcom.com>,
  Richard D Riehle <laoXhai@ix.netcom.com> wrote:
> In article <7sc6b6$c6m$1@nnrp1.deja.com>,
> 	Robert Dewar <robert_dewar@my-deja.com> wrote:
>
> >The answer is that without comments, the caller has not the
> >foggiest idea. Specifications in Ada give only the bearest
> >structural details on how to call a subprogram, they do not
> >give any hint as to what the subprogram is supposed to do!
>
> Exactly, Robert.  In the absence of assertions that can be
> checked by the compiler, comments are the only recourse. And
> you and I both agree about the problems of compiler-checked
> assertions.  An assertion can be more wrong than the program
itself.

Assertions written at the level of the language itself only
fix a very small part of this problem. And if you talk
about compiler-checked assertions, then you are reducing the
level of the assertions to a trivial level that definitely
does not begin to approach full specification (remember we
are FAR from being able to mechanically check that a full
formal specification matches an implementation in a language
at the semantic level of Ada, such checks require a large amount
of human intervention at the implementation level, e.g. adding
proof assertions).

Furthermore, full formal specifications are often neither
desirable (too opaque) nor practical (problem too complex),
nor conceptually possible (try to formalize the idea of
"nice error messages").




Sent via Deja.com http://www.deja.com/
Before you buy.




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-27  0:00                                       ` Richard D Riehle
  1999-09-28  0:00                                         ` Robert Dewar
@ 1999-09-28  0:00                                         ` Robert Dewar
  1999-09-28  0:00                                           ` "Competence" (was: 'constant functions' and access constant params) Ted Dennison
  1 sibling, 1 reply; 69+ messages in thread
From: Robert Dewar @ 1999-09-28  0:00 UTC (permalink / raw)


In article <7socka$6u4@dfw-ixnews19.ix.netcom.com>,
  Richard D Riehle <laoXhai@ix.netcom.com> wrote:
> Robert, one reason why I sometimes still look at the internal
> implemention of a subprogram is my distrust of comments over
> the life of a contract.  The comment may introduce me to what
> the subprogram does, but rarely tells me what it does not do.

Then the comments are defective, a vital part of documentation
says what the code does not do and WHY it does not do it. Bugs
in documentation are serious bugs, and competent programmers
treat them as such.

> When a contract is new, the comments are usually pretty
> reliable. As the program ages and is subjected to an increased
> level of  modification, "all bets are off."

Then it is being modified by incompetent people. yes, I
understand that this often happens, but be careful not to
create the impression that this is an inevitable or tolerable
state of affairs. Most programmers have horrible documentation
skills, and as far as I am concerned, that is a fatal flaw.
I would immediately get rid of a programmer who was not
competent at documenting their code, regardless of how
much of a wiz they were in getting things to "work".


  So it is, Robert, that I am
> so often, as you say, "completely lost."
>
> Fortunately, well-designed Ada software will export services
that
> do only one thing and are, as you so often emphasize, more
readable
> than writeable.  When looking at a C++ program, I am often
"completely
> lost" because there is so little hope of unraveling the
meaning of
> little modifications made to a program over its lifetime.  I
certainly
> cannot rely on the comments when using heavily maintained C++
code.
>
> Richard Riehle
> http://www.adaworks.com
>
>         * My copy of Hamlet is not immediately handy, but
>           I think I am pretty close to the original text.
>
>                                 Richard
>


Sent via Deja.com http://www.deja.com/
Before you buy.




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

* "Competence" (was: 'constant functions' and access constant params)
  1999-09-28  0:00                                         ` Robert Dewar
@ 1999-09-28  0:00                                           ` Ted Dennison
  1999-09-28  0:00                                             ` Robert Dewar
  0 siblings, 1 reply; 69+ messages in thread
From: Ted Dennison @ 1999-09-28  0:00 UTC (permalink / raw)


In article <7sqc54$1va$1@nnrp1.deja.com>,
  Robert Dewar <robert_dewar@my-deja.com> wrote:
> in documentation are serious bugs, and competent programmers
...
> Then it is being modified by incompetent people. yes, I

"You keep using that word. I do not think it means what you think it
means"  - Indigo Montoya (Princess Bride)

I think being labeled "competent" by Robert must be quite high praise
indeed. If ACT ever sponsors awards for coding excellence, I'd
suggest naming them the "competence awards" :-)

--
T.E.D.


Sent via Deja.com http://www.deja.com/
Before you buy.




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

* Re: "Competence" (was: 'constant functions' and access constant params)
  1999-09-28  0:00                                           ` "Competence" (was: 'constant functions' and access constant params) Ted Dennison
@ 1999-09-28  0:00                                             ` Robert Dewar
  0 siblings, 0 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-28  0:00 UTC (permalink / raw)


In article <7sqp4i$c5a$1@nnrp1.deja.com>,
  Ted Dennison <dennison@telepath.com> wrote:
> In article <7sqc54$1va$1@nnrp1.deja.com>,
>   Robert Dewar <robert_dewar@my-deja.com> wrote:
> > in documentation are serious bugs, and competent programmers
> ...
> > Then it is being modified by incompetent people. yes, I

I find your reaction to the use of the word competent odd.
Are there programming shops where lack of competence is
considered desirable?

Are there programming shops where failure to update
documentation to match code changes is considered to be
desirable, or to be a sign of competence?

I would think the answer to both questions would be no, but
you never know, we read some strange things on CLA :-)



Sent via Deja.com http://www.deja.com/
Before you buy.




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-28  0:00                                         ` Robert Dewar
@ 1999-09-28  0:00                                           ` Richard D Riehle
  1999-09-29  0:00                                             ` Robert A Duff
  1999-09-29  0:00                                             ` Robert Dewar
  0 siblings, 2 replies; 69+ messages in thread
From: Richard D Riehle @ 1999-09-28  0:00 UTC (permalink / raw)


In article <7sqbt6$1la$1@nnrp1.deja.com>,
	Robert Dewar <robert_dewar@my-deja.com> wrote:

>Assertions written at the level of the language itself only
>fix a very small part of this problem. And if you talk
>about compiler-checked assertions, then you are reducing the
>level of the assertions to a trivial level that definitely
>does not begin to approach full specification (remember we
>are FAR from being able to mechanically check that a full
>formal specification matches an implementation in a language
>at the semantic level of Ada, such checks require a large amount
>of human intervention at the implementation level, e.g. adding
>proof assertions).

I agree with most of your observations here.  Even Bertrand Meyer,
advocate of "design by contract" through assertions, agrees that
we have not yet reached a point in software design where we can
rely on a compiler to "prove" the validity of an assertion.  Of
greater concern is that one can construct an assertion so complex
that no current theorem-proving software can guarantee its correctness.
As much as I agree with Parnas, Gries, Dijkstra, and Knuth about the
desirability of assertions, I continue to be skeptical of their
usefulness in large-scale software systems.  

>Furthermore, full formal specifications are often neither
>desirable (too opaque) nor practical (problem too complex),
>nor conceptually possible (try to formalize the idea of
>"nice error messages").

Once again, I mostly agree.  On the other hand, I have been
encountering some really interesting work in formal specifications
coming from the European computing community.  I don't understand
all of what I see, but what I do understand is impressive.  It is
that kind of work that makes me optimistic about the potential for
formal specifications in the future.  

The people who follow us in creating the equivalent of software a
hundred years from now will look back on what we are doing today
with the same regard we give mathematicians in the time of Charlemagne.

Richard Riehle
http://www.adaworks.com


>
>
>
>Sent via Deja.com http://www.deja.com/
>Before you buy.

 




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-28  0:00                                           ` Richard D Riehle
  1999-09-29  0:00                                             ` Robert A Duff
@ 1999-09-29  0:00                                             ` Robert Dewar
  1 sibling, 0 replies; 69+ messages in thread
From: Robert Dewar @ 1999-09-29  0:00 UTC (permalink / raw)


In article <7sr6gl$soc@dfw-ixnews19.ix.netcom.com>,
  Richard D Riehle <laoXhai@ix.netcom.com> wrote:
>  On the other hand, I have been
> encountering some really interesting work in formal
specifications
> coming from the European computing community.  I don't
understand
> all of what I see, but what I do understand is impressive.  It
is
> that kind of work that makes me optimistic about the potential
for
> formal specifications in the future.


Sure, but so far the most important achievment in the formal
specification area over the last decade has been to realize
that the problem is far more difficult than we thought :-)


Sent via Deja.com http://www.deja.com/
Before you buy.




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

* Re: 'constant functions' and access constant params (was Re: Array of Variant Records Question...)
  1999-09-28  0:00                                           ` Richard D Riehle
@ 1999-09-29  0:00                                             ` Robert A Duff
  1999-09-29  0:00                                             ` Robert Dewar
  1 sibling, 0 replies; 69+ messages in thread
From: Robert A Duff @ 1999-09-29  0:00 UTC (permalink / raw)


Richard D Riehle <laoXhai@ix.netcom.com> writes:

> I agree with most of your observations here.  Even Bertrand Meyer,
> advocate of "design by contract" through assertions, agrees that
> we have not yet reached a point in software design where we can
> rely on a compiler to "prove" the validity of an assertion. ...

It's not just that we haven't "yet" reached such a point.  Look at one
of Robert Dewar's favorite examples (also one of my favorites): An
important requirement for a compiler is to produce clear error messages.
But you can't *prove* anything like that (in the mathematical sense).
It's hard to see how anybody could *ever* prove it, because it seems
impossible to formalize the notion of a "clear error message" in a way
that doesn't lose the essense of that notion.

I think I remember an argument crossposted to here and comp.lang.eiffel,
in which both Robert and Bertrand Meyer participated.  As I recall,
Meyer's response to the above point was to deny that "clear error
messages" makes any sense as a requirement.  I claim it *does* make
sense.  Certainly, I know a bad error message when I see one.  You could
even *measure* it scientifically -- observe people programming, and
measure how long it takes them (on average) to figure out and fix what
the compiler is complaining about.  The fact that you can't prove
anything about it mathematically doesn't mean it's somehow unreal or
irrelevant.

I'm not sure I fully understood Meyer -- after all, Eiffel allows
*comments* as assertions, syntactically, which suggests that he allows
for the possibility of requirements that are not formalizable.

>...  Of
> greater concern is that one can construct an assertion so complex
> that no current theorem-proving software can guarantee its
> correctness.

I'm not sure how this differs from your previous point.

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




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

end of thread, other threads:[~1999-09-29  0:00 UTC | newest]

Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-09-08  0:00 Array of Variant Records Question Bruce Detter
1999-09-08  0:00 ` Thank you Bruce Detter
1999-09-08  0:00   ` Martin C. Carlisle
1999-09-08  0:00 ` Array of Variant Records Question Martin C. Carlisle
1999-09-08  0:00 ` Matthew Heaney
1999-09-08  0:00   ` Mike Silva
1999-09-08  0:00     ` Matthew Heaney
1999-09-09  0:00       ` Robert Dewar
1999-09-09  0:00         ` Matthew Heaney
1999-09-09  0:00           ` Matthew Heaney
1999-09-09  0:00             ` Robert Dewar
1999-09-09  0:00             ` Mark Lundquist
1999-09-09  0:00           ` Robert Dewar
1999-09-09  0:00             ` Matthew Heaney
1999-09-10  0:00               ` Robert Dewar
1999-09-10  0:00                 ` Mark Lundquist
1999-09-10  0:00                   ` Matthew Heaney
1999-09-11  0:00                     ` Jean-Pierre Rosen
1999-09-14  0:00                     ` "cast away const" (was Re: Array of Variant Records Question...) Mark Lundquist
     [not found]                     ` <wccd7viiv59.fsf@world.std.com>
     [not found]                       ` <7rrmqd$l89@drn.newsguy.com>
     [not found]                         ` <wcciu59n2uf.fsf@world.std.com>
1999-09-22  0:00                           ` Array of Variant Records Question Robert I. Eachus
1999-09-23  0:00                             ` Robert Dewar
1999-09-23  0:00                               ` Robert I. Eachus
1999-09-22  0:00                       ` Robert I. Eachus
1999-09-10  0:00               ` Mark Lundquist
1999-09-10  0:00                 ` Matthew Heaney
1999-09-11  0:00                 ` Robert Dewar
1999-09-11  0:00               ` Richard D Riehle
1999-09-13  0:00                 ` Hyman Rosen
1999-09-14  0:00                 ` Mark Lundquist
     [not found]                   ` <7roohh$s6r@dfw-ixnews7.ix.netcom.com>
     [not found]                     ` <37e01168@news1.prserv.net>
     [not found]                       ` <7rp86o$c6h@dfw-ixnews3.ix.netcom.com>
     [not found]                         ` <37E18CC6.C8D431B@rational.com>
     [not found]                           ` <7rs8bn$s6@dfw-ixnews4.ix.netcom.com>
     [not found]                             ` <wccemfxn15s.fsf@world.std.com>
1999-09-22  0:00                               ` 'constant functions' and access constant params (was Re: Array of Variant Records Question...) Richard D Riehle
     [not found]                             ` <37e2e58c@news1.prserv.net>
1999-09-22  0:00                               ` Richard D Riehle
1999-09-22  0:00                                 ` Mark Lundquist
1999-09-22  0:00                                   ` Mark Lundquist
1999-09-22  0:00                                 ` Matthew Heaney
1999-09-22  0:00                                   ` Richard D Riehle
1999-09-22  0:00                                     ` Matthew Heaney
1999-09-22  0:00                                     ` Matthew Heaney
1999-09-23  0:00                                       ` Vincent Marciante
1999-09-23  0:00                                         ` Matthew Heaney
1999-09-24  0:00                                       ` Robert A Duff
1999-09-25  0:00                                         ` Matthew Heaney
1999-09-27  0:00                                       ` Richard D Riehle
1999-09-27  0:00                                       ` Richard D Riehle
1999-09-27  0:00                                         ` David Kristola
1999-09-23  0:00                                     ` Robert Dewar
1999-09-27  0:00                                       ` Richard D Riehle
1999-09-28  0:00                                         ` Robert Dewar
1999-09-28  0:00                                           ` Richard D Riehle
1999-09-29  0:00                                             ` Robert A Duff
1999-09-29  0:00                                             ` Robert Dewar
1999-09-28  0:00                                         ` Robert Dewar
1999-09-28  0:00                                           ` "Competence" (was: 'constant functions' and access constant params) Ted Dennison
1999-09-28  0:00                                             ` Robert Dewar
1999-09-09  0:00             ` Array of Variant Records Question Brian Rogoff
1999-09-13  0:00               ` Matthew Heaney
1999-09-13  0:00                 ` Robert A Duff
1999-09-13  0:00                   ` Matthew Heaney
1999-09-13  0:00                 ` Brian Rogoff
1999-09-14  0:00                   ` Robert Dewar
1999-09-14  0:00                   ` Robert Dewar
1999-09-14  0:00                     ` Brian Rogoff
1999-09-10  0:00             ` Proposed Ada features (was Re: Array of Variant Records Question...) Mark Lundquist
1999-09-10  0:00               ` Matthew Heaney
1999-09-10  0:00                 ` tmoran
1999-09-09  0:00     ` Array of Variant Records Question Nick Roberts
1999-09-09  0:00       ` Tucker Taft
1999-09-10  0:00         ` Nick Roberts
1999-09-09  0:00       ` Robert Dewar
1999-09-08  0:00 ` Ted Dennison

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