comp.lang.ada
 help / color / mirror / Atom feed
From: Niklas Holsti <niklas.holsti@tidorum.invalid>
Subject: Re: formal array types and default values
Date: Sat, 6 Jan 2018 02:10:30 +0200
Date: 2018-01-06T02:10:30+02:00	[thread overview]
Message-ID: <fbaifmFd3gjU1@mid.individual.net> (raw)
In-Reply-To: <p2jfs7$cl3$1@franka.jacob-sparre.dk>

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" <niklas.holsti@tidorum.invalid> 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
       .      @       .


  reply	other threads:[~2018-01-06  0:10 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-30 21:42 formal array types and default values Mehdi Saada
2017-12-30 22:20 ` Niklas Holsti
2017-12-30 23:59   ` Mehdi Saada
2018-01-03  0:52   ` Randy Brukardt
2018-01-03  8:33     ` Niklas Holsti
2018-01-03 20:53       ` Randy Brukardt
2018-01-06  0:10         ` Niklas Holsti [this message]
2018-01-08 21:12           ` Randy Brukardt
2017-12-31 12:34 ` Jeffrey R. Carter
2017-12-31 14:55   ` Mehdi Saada
2018-01-03 15:47 ` Mehdi Saada
2018-01-03 21:16   ` Randy Brukardt
2018-01-04 15:02 ` Mehdi Saada
replies disabled

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