From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,c63aa81a67eceb8f X-Google-Attributes: gid103376,public From: "Nick Roberts" Subject: Re: Ragged Array Proposal Date: 1999/09/23 Message-ID: <37eaa24b@eeyore.callnetuk.com> X-Deja-AN: 528814883 References: <37e7c08e@eeyore.callnetuk.com> <7satei$e2q$1@nnrp1.deja.com> <37EA4E91.1D4D1FC@averstar.com> X-Original-NNTP-Posting-Host: da128d202.dialup.callnetuk.com X-Trace: 23 Sep 1999 22:57:31 GMT, da128d202.dialup.callnetuk.com X-MSMail-Priority: Normal X-Priority: 3 Newsgroups: comp.lang.ada X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300 Date: 1999-09-23T00:00:00+00:00 List-Id: Tucker Taft wrote in message news:37EA4E91.1D4D1FC@averstar.com... [...] | If you change Command_String_Ptr to be "access constant String;" then | the recommended implementation does *not* duplicate the static data. | It is link-time allocated and initialized. This might vary by compiler, | but anything having to do with link-time initialization is an "optimization," | so that is true even for static constants. I know at least that the | Aonix and Green Hills Ada 95 compilers statically allocate and initialize | allocators for access-to-constant types. I haven't checked GNAT. [...] My contention is that using an access type and allocators is unappealing simply because the programmer is forced to use an access type and allocators for doing something _really simple_: declaring an array of strings! With the greatest respect, it is perhaps easy for those of you who are steeped in knowledge of the language to overlook this (and there can be no arguing that STT is steeped in knowledge of the language!). Try telling a C++ programmer that, in Ada, they have to declare an access type, and then repeat the "new String'("xyz")" incantation for every string, just to declare an array of strings, and they might be likely to say "Ada? No thanks, I'll stick to C++, if you don't mind." Frankly, the pre-allocation trick (which is fine and dandy in all other respects) only makes things worse from this point of view (simplicity for the programmer), since it makes it looks like something is happening (dynamic allocation) which is actually not. I agree with the idea that Ada language constructs should not be too divorced from their likely underlying implementations, and this seems like a rare example of Ada committing this sin. I would agree that ragged arrays commit the same sin, but I would say less so. To those who argue that adding ragged arrays would add unnecessary complexity to the language, my reply is not to confuse complexity of the language with complexity of _using_ the language. It would unarguably simplify the language tremendously to remove arrays, records, generics, tagged types, subprograms, etc., but it wouldn't simplify using the language. My argument is that ragged arrays would add relatively little to the complexity of the language, but would, in practice, very often simplify using the language a great deal. I think the example of the ragged array in a record demonstrates the most serious reason for introducing ragged arrays. Think about the likely underlying implementation for this (an array of pointers or offsets and a block of data, all totally internal to the record), and then think about how the same thing could be done in existing Ada 95. In general, the closest you can get in Ada 95 is to use an access type (either to the array as a whole, or to the components of the array), and dynamic allocation. The ragged array will generally be more efficient: if your program is going to have multiple objects constrained to the same subtype of the record (a very likely scenario), the 'dope' information only needs to be stored once, saving memory; the necessity to call upon the allocator to allocate either the array or its components is avoided, saving processor time; the necessity to declare access types and mess around with the associated paraphernalia can be avoided (saving hair, in extreme cases :-). Ted Dennison wrote: | One thing confuses me about your proposal. You say that when the array | is declared all the elements will be constrained. But then you say that | you can dynamicly change elements. Are you saying that if I try to | assign a 5 character string into an array element that is a 4 character | string, the compiler would accept it? If so, how about if a function | returns a 5 character string? Or how about if the 4 character string | element in the ragged array is passed into a subprogram as an "out" or | "in out" parameter? I'm not quite sure where I say this, Ted, but I hope I can clarify things using your examples. The subtypes of the components of a ragged array, called the 'profile' of the array, form part of the constraint of the array. Supposing we declared an 'array of strings' ragged array type: type String_Array is array (Positive range <>) of String; we could then declare an object of this type, constrained to, say, three components, with a profile of, say, a 3-character string, a 4-character string, and a 5-character string: People: String_Array(1..3)(String(1..3),String(1..4),String(1..5)); Note the 'profiled constraint': an ordinary index constraint, followed by an 'array profile'. Alternatively, the object could have been constrained by an initial value: People: String_Array := ("Tom","Dick","Harry"); (Note the nice, simple syntax.) Either way, People is now permanently constrained, both in terms of its indexes and its profile. The assignment: People(2) := "Jane"; would be perfectly all right, since People(2) is a 4-character string. However, either of: People(3) := "Jane"; People(2) := "Emily"; would raise Constraint_Error. Nothing can change either the index subtype or the profile of People, and its components follow the same rules they would as stand-alone objects. Since the actual parameter matching an 'out' or 'in out' mode formal parameter must be an object, and all objects of an array type - including my proposed ragged array type - must be constrained, the constraint, including the profile of a ragged array, would be passed in upon a call to the procedure, just as with all other mutable types, and the procedure could not change the constraint. As for a function result, since function return types (as well as any subprogram parameter types) are allowed to be unconstrained, a function could be declared which had simply String_Array as its return type, and then the function could return results with any compatible subtype (i.e. any index range and any profile). For example, a function could be defined to reverse the order of the components of a string array: function Reverse_Order (A: in String_Array) return String_Array; and then the expression Reverse_Order(("Tom","Dick","Harry")) would return the array ("Harry","Dick","Tom"). It is significant to note that the implementation of this function would have to be highly inefficient (involving repeated slicing and concatenating). This illustrates that there would often be situations where an array of access values would be far preferable to a ragged array. My argument is that, conversely, there would often be situations where a ragged array would be preferable to an array of access values. I'm grateful to Ted for his compliment on the appearance of my site (I'll try to maintain the standard!), and I'm very grateful to people taking the time to look at my proposal and post comments. Best wishes, ------------------------------------- Nick Roberts http://www.callnetuk.com/home/nickroberts http://www.adapower.com/lab/adaos ------------------------------------- PS: I'm not at all emotionally attached to the nomenclature that I've invented (even the name "ragged array"), and not entirely happy with it, so suggestions for improvements gratefully accepted. The same goes for the syntax. PPS: Hold on to your hats, folks! Next up is going to be a 'single derived object' proposal. I haven't finished with you yet :-)