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 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: formal array types and default values Date: Sat, 6 Jan 2018 02:10:30 +0200 Organization: Tidorum Ltd Message-ID: References: <053b2370-5c15-4662-a9e3-e1464de206a1@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net gTJR2wPDrp7udk7xpEpVSwQZ8tFVW5vk2h6x3WlnywmzlOQKX2 Cancel-Lock: sha1:NDXDFGYMmC5gn8EhtfMkfem5KFo= User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 In-Reply-To: Xref: reader02.eternal-september.org comp.lang.ada:49774 Date: 2018-01-06T02:10:30+02:00 List-Id: While I am continuing this discussion of why the Default_Component_Value aspect is limited to scalars, and only to static scalar expressions, which is perhaps not of much interest, I first want to say that I am quite willing to believe the ARG if they reject or limit a new Ada feature because of implementation difficulty. The large effort required to implement and maintain an Ada compiler, compared to the relatively small market (whether paying or non-paying) for those compilers, is a challenge to the viability of the language. I would prefer to have more good compilers for the present language than to have nice new language features that are not generally implemented. On 18-01-03 22:53 , Randy Brukardt wrote: > "Niklas Holsti" wrote in message > news:fb3iqsFnjd7U1@mid.individual.net... > ... >> generic >> >> type T is private; >> >> Null_Value : in T; >> >> package Foo is >> >> type Vector is array (Positive range <>) of T >> with Default_Component_Value => Null_Value; >> >> end Foo; >> >> Following the current rules, GNAT rejects this because Null_Value >> is not (always) a scalar. >> >> If the generic formal type T is changed to "type T is range <>", >> GNAT accepts the generic package declaration, but accepts an >> instantiation only if Null_Value is given a static expression >> (this is GNAT GPL 2012 on Mac). > > Correct. And you can't do it at all in the body (as a formal object > will not be considered static there). > > I forget the reason that we required staticness, but I think it had > something to do with when the default expression is evaluated. From the discussion in AI05-0228, it seems to be related also to type freezing: Robert Dewar reported "huge problems" implementing the Default_Value aspect, and Randy Brukardt replied: "The key is to note that as these have to be static expressions, they can't involve the creation of any default-initialized objects (no user-defined function calls). Thus, I would suggest that the best approach would be to handle Default_Value aspects immediately *after* freezing of the type (but before anything else that depends on freezing." ... "If there is anything that would be a problem, the checking for a static expression will catch it." However, I found no discussion in the AI re *why* the AI was initially written to require a static expression for Default_Value, nor why Default_Component_Value is limited to scalars. > It seemed > confusing to do it just once at the point of declaration (most Ada defaults > are re-evaluated), but we didn't want to incur the expense of having to > evaluate an expression for every initialization. From the programmer's view, it would IMO have been preferable to make Default_Value and Default_Component_Value work more like the default values of record components. Of course that effect can still be achieved by wrapping the scalar values into single-component records, but that is rather inconvenient (in the AI, Bob Duff calls this wrapping "extremely painful"). Worrying about the expense should IMO have been left to the application designer, who can choose to use a static expression, or a precomputed non-static constant, if the expense would be important for the application. However, I do see that in a code-sharing generic, the expense of a non-static-expression Default_[Component_]Value, evaluated anew for every object or component to be initialized, could be quite a lot higher than for a static expression, for which the issue of evaluating once, or per each object/component, does not arise. Perhaps a good compromise, from the expense point of view, would have been to allow a non-static but constant expression, resulting in a single evaluation. >> The drawback of the current restrictions (when T is private) is that the >> responsibility for the assignment of a default value for the components of >> the Vector type is placed on the /client/ of the generic package, who must >> set the default value for the actual type T. Moreover, it is now >> impossible to have different default component values for different arrays >> declared in the generic, because type T can have only one default value. > > Defaults always belong to a type, so by definition, they are always set at > the point of the type declaration. Subtype-specific defaults caused a > nightmare of problems since not every object has a well-defined nominal > subtype. Yes, we already discussed that default values are per type and not per subtype. I did not mean to imply, above, that the "different arrays" would be merely different subtypes. They would be different array types, as in the example that followed. > Thus, if the client is defining the type, they have to define the > defaults. QED. :-) IMO the party who defines a type should be responsible for the initial default value. Here it is the _generic_ that defines the _array_ type, not the client, and the issue is the Default_Component_Value for the _array_ type. (Sorry, I don't know a suitable Latin acronym for "not QED".) > As for the private type case, Ada is very strict about its contract model of > generics, and we don't allow things that don't make sense. And defining a > default component value of a non-scalar type doesn't make sense, because the > component value can't be static. Thus it is never legal in a generic. That is not the question. The question that started this thread is *why* the Default_Component_Value must be (a) static and (b) a scalar, and the question was raised *because* these rules prevented the OP from writing the generic they wanted to write. > We adopted the restrictions on these aspects (Default_Value and > Default_Component_Value) in order to make them tractable. Had someone > insisted on allowing subtypes and non-static values, they become too complex > to describe and implement. (They have effects on parameter passing and in > aggregates as well as the "obvious" effects). I read the relevant ARM parts on parameter passing and aggregates and Default_[Component_]Value, but could not see anything that would require staticity or scalarity. For parameter passing, the issue seems to be only that the initial value of a formal "out" parameter passed by copy is now required to be the Default_Value of the actual parameter, implicitly "copied in" (RM6.4.1(5.1/4..5.3/4 and 13.1/4..13.4/4)). For aggregates, the issue seems to be only that a <> expression should use the Default_Component_Value, if specified for this array type (RM4.3.3(23.1/4)). > I most likely would have voted > to kill them in that case, and I think others were leaning the same way. Ok, as I said, if the issue was considered and the static scalar limitation chosen as the only feasible one, I certainly prefer to have the feature in this limited form, than not to have it at all. >> One can imagine, for example, that T represents a value in some algebra >> that has both a "zero" value (neutral element for addition) and a "one" >> value (neutral element for multiplication), and that the generic package >> would like to use "zero" as the default component value for one array type >> ("array of sums") but use "one" as the default component value for another >> array type ("array of products"). > > That problem is best solved by a reduction expression in Ada 2020, so no one > will end up writing this generic anyway (they'll want to potentially > parallel execution of a reduction expression). :-) You are diverting the discussion to a particular (poorly relevant) aspect of the example, rather than addressing the point. > In any case, a default value is a convinience feature; no one ought to be > writing uninitialized object declarations in the first place. I agree that uninitialized objects are poisonous, but I think that the ability to specify default initial values via the type system is an important means for avoiding such objects. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .