* Array of Variant Records Question... @ 1999-09-08 0:00 Bruce Detter 1999-09-08 0:00 ` Matthew Heaney ` (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 Array of Variant Records Question Bruce Detter @ 1999-09-08 0:00 ` Matthew Heaney 1999-09-08 0:00 ` Mike Silva 1999-09-08 0:00 ` Thank you Bruce Detter ` (2 subsequent siblings) 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
* 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
* 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-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 ` Mark Lundquist 1999-09-09 0:00 ` Robert Dewar 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 ` Mark Lundquist 1999-09-09 0:00 ` Robert Dewar 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 ` Matthew Heaney 1999-09-09 0:00 ` Mark Lundquist @ 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 <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 ` Brian Rogoff ` (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 ` Brian Rogoff 1999-09-13 0:00 ` Matthew Heaney 1999-09-09 0:00 ` Matthew Heaney 1999-09-10 0:00 ` Proposed Ada features " 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 ` Brian Rogoff @ 1999-09-13 0:00 ` Matthew Heaney 1999-09-13 0:00 ` Brian Rogoff 1999-09-13 0:00 ` Robert A Duff 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 ` Brian Rogoff 1999-09-14 0:00 ` Robert Dewar 1999-09-14 0:00 ` Robert Dewar 1999-09-13 0:00 ` Robert A Duff 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-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
* 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: Array of Variant Records Question... 1999-09-13 0:00 ` Matthew Heaney 1999-09-13 0:00 ` Brian Rogoff @ 1999-09-13 0:00 ` Robert A Duff 1999-09-13 0:00 ` Matthew Heaney 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-09 0:00 ` Robert Dewar 1999-09-09 0:00 ` Brian Rogoff @ 1999-09-09 0:00 ` Matthew Heaney 1999-09-10 0:00 ` Robert Dewar ` (2 more replies) 1999-09-10 0:00 ` Proposed Ada features " 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-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
* 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: 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-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
* "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
[parent not found: <wccd7viiv59.fsf@world.std.com>]
[parent not found: <7rrmqd$l89@drn.newsguy.com>]
[parent not found: <wcciu59n2uf.fsf@world.std.com>]
* 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: 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: 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: 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... 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 ` 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 ` 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-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-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-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
[parent not found: <7roohh$s6r@dfw-ixnews7.ix.netcom.com>]
[parent not found: <37e01168@news1.prserv.net>]
[parent not found: <7rp86o$c6h@dfw-ixnews3.ix.netcom.com>]
[parent not found: <37E18CC6.C8D431B@rational.com>]
[parent not found: <7rs8bn$s6@dfw-ixnews4.ix.netcom.com>]
[parent not found: <wccemfxn15s.fsf@world.std.com>]
* 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
[parent not found: <37e2e58c@news1.prserv.net>]
* 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 ` Matthew Heaney 1999-09-22 0:00 ` Mark Lundquist 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 ` Matthew Heaney 1999-09-22 0:00 ` Richard D Riehle 1999-09-22 0:00 ` Mark Lundquist 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 ` 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: '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 ` 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 ` 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: '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-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 ` David Kristola 1999-09-27 0:00 ` Richard D Riehle 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-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 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-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: '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 ` 'constant functions' and access constant params (was Re: Array of Variant Records Question...) 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 ` "Competence" (was: 'constant functions' and access constant params) Ted Dennison 1999-09-28 0:00 ` 'constant functions' and access constant params (was Re: Array of Variant Records Question...) 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: > 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-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 ` Richard D Riehle 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-28 0:00 ` 'constant functions' and access constant params (was Re: Array of Variant Records Question...) 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 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
* 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-22 0:00 ` Richard D Riehle 1999-09-22 0:00 ` Matthew Heaney @ 1999-09-22 0:00 ` Mark Lundquist 1999-09-22 0:00 ` Mark Lundquist 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
* Proposed Ada features (was Re: Array of Variant Records Question...) 1999-09-09 0:00 ` Robert Dewar 1999-09-09 0:00 ` Brian Rogoff 1999-09-09 0:00 ` Matthew Heaney @ 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 " 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: 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-08 0:00 ` Mike Silva 1999-09-08 0:00 ` Matthew Heaney @ 1999-09-09 0:00 ` Nick Roberts 1999-09-09 0:00 ` Robert Dewar 1999-09-09 0:00 ` Tucker Taft 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 ` Robert Dewar 1999-09-09 0:00 ` Tucker Taft 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 ` Robert Dewar @ 1999-09-09 0:00 ` Tucker Taft 1999-09-10 0:00 ` Nick Roberts 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 ` 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
* Thank you 1999-09-08 0:00 Array of Variant Records Question Bruce Detter 1999-09-08 0:00 ` Matthew Heaney @ 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 1999-09-08 0:00 ` Ted Dennison 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 Array of Variant Records Question Bruce Detter 1999-09-08 0:00 ` Matthew Heaney 1999-09-08 0:00 ` Thank you Bruce Detter @ 1999-09-08 0:00 ` Martin C. Carlisle 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 ` (2 preceding siblings ...) 1999-09-08 0:00 ` Array of Variant Records Question Martin C. Carlisle @ 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
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 ` 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 ` Mark Lundquist 1999-09-09 0:00 ` Robert Dewar 1999-09-09 0:00 ` Robert Dewar 1999-09-09 0:00 ` Brian Rogoff 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-13 0:00 ` Robert A Duff 1999-09-13 0:00 ` Matthew Heaney 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 ` 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 ` David Kristola 1999-09-27 0:00 ` Richard D Riehle 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 ` "Competence" (was: 'constant functions' and access constant params) Ted Dennison 1999-09-28 0:00 ` Robert Dewar 1999-09-28 0:00 ` 'constant functions' and access constant params (was Re: Array of Variant Records Question...) 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-22 0:00 ` Mark Lundquist 1999-09-22 0:00 ` Mark Lundquist 1999-09-10 0:00 ` Proposed Ada features " 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 ` Robert Dewar 1999-09-09 0:00 ` Tucker Taft 1999-09-10 0:00 ` Nick Roberts 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 ` Ted Dennison
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox