comp.lang.ada
 help / color / mirror / Atom feed
* formal array types and default values
@ 2017-12-30 21:42 Mehdi Saada
  2017-12-30 22:20 ` Niklas Holsti
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Mehdi Saada @ 2017-12-30 21:42 UTC (permalink / raw)


I have several questions more or less related.
First: why aspect DEFAULT_COMPONENT_VALUE can apply only to components of scalar type ? It would be nice to be able to set a default value to an array type in a generic package, equal to a generic object parameter.

type T_Vect_Coef is array (T_Degre range <>) of ELEMENT;
gives that message:
main.adb:21:22: unconstrained subtype not allowed (need initialization)
main.adb:21:22: provide initial value or explicit array bounds

ELEMENT and T_DEGRE are generic and declared like that:
type ELEMENT is private;
type T_DEGRE is range <>;

Those two types are public. How can I give a default value, since DEFAULT_COMPONENT_VALUE doesn't apply to non scalar types.

In the private part,
the type
type T_Polynome (Degre : T_Degre := 0) is -- type mutant
    record
        COEF : T_Vect_Coef (0..Degre) := (others => NULL_ELEMENT);
    end record;
gives that warning: creation of "T_Polynome" object may raise Storage_Error. Why?


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

* Re: formal array types and default values
  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
  2017-12-31 12:34 ` Jeffrey R. Carter
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 13+ messages in thread
From: Niklas Holsti @ 2017-12-30 22:20 UTC (permalink / raw)


On 17-12-30 23:42 , Mehdi Saada wrote:
> I have several questions more or less related.

> First: why aspect DEFAULT_COMPONENT_VALUE can apply only
> to components of scalar type ?

Don't know. Perhaps the thought was that if the component is a record 
type, then there is already a way to give default values to the 
components of the record type.

However, the AARM explains that this is a representation attribute, and 
why that is so, and (therefore?) requires the default component value to 
be defined by a /static/ expression, which means that it can only be a 
scalar or a string. In principle, a string might define the default 
component value of an array with elements of a constrained String 
subtype, but that is probably not a very common case.

> It would be nice to be able  to set a default value to an array type
> in a generic package, equal to a generic object parameter.

Agreed. Possibly this case was forgotten, or prevented by such a generic 
object parameter not being a static value.

> type T_Vect_Coef is array (T_Degre range <>) of ELEMENT;
> gives that message:
> main.adb:21:22: unconstrained subtype not allowed (need initialization)
> main.adb:21:22: provide initial value or explicit array bounds

I'm pretty sure that these messages don't come from the type 
declaration, but from some place where you declare a variable of this 
type, without giving bounds or an initial value, as in:

    Coef : T_Vect_Coef;

As the index range of T_Vect_Coef is not constrained, the index bounds 
of Coef would be indeterminate. The messages are telling you to either 
provide index bounds, as in:

    Coef : T_Vect_Coef (0 .. 42);

or to provide an initial value that then defines the index bounds, as in:

    Coef : T_Vect_Coef := (0 => 23, 1 => 66, 2 .. 15 => 0);

> ELEMENT and T_DEGRE are generic and declared like that:
> type ELEMENT is private;
> type T_DEGRE is range <>;
>
> Those two types are public.

Huh? If these types are generic formal types, I do not understand what 
you mean by "public".

> How can I give a default value, since
> DEFAULT_COMPONENT_VALUE doesn't apply to non scalar types.
>
> In the private part,
> the type
> type T_Polynome (Degre : T_Degre := 0) is -- type mutant
>     record
>         COEF : T_Vect_Coef (0..Degre) := (others => NULL_ELEMENT);
>     end record;
> gives that warning: creation of "T_Polynome" object may raise Storage_Error. Why?

Usually this error message means the following:

- As an initial value was provided for Degre, it is possible to define 
unconstrained variables of type T_Polynome, and such a variable should 
be able to handle any value of Degre.

- In order to handle any value of Degre, the variable will be sized 
according to maximum size that can be required, which here occurs for 
Degre = T_Degre'Last. (Some compilers will allocate the COEF component 
on the heap, according to the actual value of Degre, and then will not 
have this problem. However, GNAT uses the allocate-maximum-size method.)

- But T_Degre'Last is (or can be) so large that it will be impossible to 
create a T_Polynome (Degre => T_Degre'Last), and therefore Storage_Error 
will be raised.

The remedy is to place som reasonable upper bound on the maximum 
possible value of Degre, by defining the type of Degree with a 
reasonable 'Last.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

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

* Re: formal array types and default values
  2017-12-30 22:20 ` Niklas Holsti
@ 2017-12-30 23:59   ` Mehdi Saada
  2018-01-03  0:52   ` Randy Brukardt
  1 sibling, 0 replies; 13+ messages in thread
From: Mehdi Saada @ 2017-12-30 23:59 UTC (permalink / raw)


> If these types are generic formal types, I do not understand what 
> you mean by "public".
Sorry. The array is a public (as opposed to "private" ?) type, T_DEGRE and ELEMENT are formal generic parameters.

> Some compilers will allocate the COEF component 
> on the heap, according to the actual value of Degre, and then will not 
> have this problem. However, GNAT uses the allocate-maximum-size method.)
I would have liked to have the choice, through, say, an aspect Dynamic_Bounds_Checking, or somethin'

> The remedy is to place som reasonable upper bound on the maximum 
> possible value of Degre, by defining the type of Degree with a 
> reasonable 'Last.
It was indeed done initially in the package, but I thought I was smarter and removed it. Wrong...

Thanks for your insight.


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

* Re: formal array types and default values
  2017-12-30 21:42 formal array types and default values Mehdi Saada
  2017-12-30 22:20 ` Niklas Holsti
@ 2017-12-31 12:34 ` Jeffrey R. Carter
  2017-12-31 14:55   ` Mehdi Saada
  2018-01-03 15:47 ` Mehdi Saada
  2018-01-04 15:02 ` Mehdi Saada
  3 siblings, 1 reply; 13+ messages in thread
From: Jeffrey R. Carter @ 2017-12-31 12:34 UTC (permalink / raw)


On 12/30/2017 10:42 PM, Mehdi Saada wrote:
> 
> type T_Vect_Coef is array (T_Degre range <>) of ELEMENT;
> gives that message:
> main.adb:21:22: unconstrained subtype not allowed (need initialization)
> main.adb:21:22: provide initial value or explicit array bounds

I can't tell from the information you've provided (a small reproducer is usually 
a good idea), but this looks to me like the error msg GNAT gives for something like

S : String;

> type T_Polynome (Degre : T_Degre := 0) is -- type mutant
>      record
>          COEF : T_Vect_Coef (0..Degre) := (others => NULL_ELEMENT);
>      end record;
> gives that warning: creation of "T_Polynome" object may raise Storage_Error. Why?

Because the descriminant has a default, it's possible to declare

V : T_Polynome;

This initially has Degre => 0, but by full-record assignment, you can change the 
discriminant:

V := (Degre => 42, Coef => (0 .. 42 => Something) );

There are 2 ways a compiler can implement this. Janus/Ada will put the Coef 
component on the heap (with bounds 0 .. 0), so that the part of the record that 
is on the stack will be a constant size. If you change the discriminant, it will 
deallocate the existing Coef and allocate a new one with the new bounds. This 
approach is easier to use, but adds some overhead. For most application domains 
on most modern computers, the difference is not significant.

GNAT allocates space for the largest variant on the stack, and only uses the 
part needed by the current discriminant. When the discriminant changes, the part 
of the allocated space being used changes also. The stack is usually much 
smaller than the heap, and if T_Degre'Last is large, the amount of space to be 
allocated may exceed the size of the stack, resulting in Storage_Error. This 
approach avoids the overhead of heap allocation and deallocation, but is a bit 
less user friendly.

Some people claim that Ichbiah (the designer of Ada 83) intended this to be 
implemented the way Janus/Ada does. The Alsys and Meridian compilers also did 
this, and Alsys was Ichbiah's company, so perhaps they're correct. On the other 
hand, the DEC compiler used the same technique as GNAT, and when I heard Ichbian 
talk about the DEC compiler he had only praise for it. In the absence of a 
requirement or even advice on how to implement this in the ARM, either approach 
is correct.

There are application domains in which implicit heap allocation cannot be 
tolerated, but for most applications on modern computers with GB of RAM, the 
developer doesn't care where in RAM objects go, and it would be nice if 
compilers for such systems had a mode in which objects too large to fit on the 
stack would be automatically allocated on the heap.

-- 
Jeff Carter
"Of course, one couldn't think properly in Paris--
it was so uncomfortable and the houses were
central heated."
Clouds of Witness
153


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

* Re: formal array types and default values
  2017-12-31 12:34 ` Jeffrey R. Carter
@ 2017-12-31 14:55   ` Mehdi Saada
  0 siblings, 0 replies; 13+ messages in thread
From: Mehdi Saada @ 2017-12-31 14:55 UTC (permalink / raw)


No mystery, then.
Indeed there a declared variable without initial value nor a constrained anonymous subtype. I saw it just before reading your precedent message, wrote a new, lost it, rewrote it, then forgot saying it again !

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

* Re: formal array types and default values
  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
  1 sibling, 1 reply; 13+ messages in thread
From: Randy Brukardt @ 2018-01-03  0:52 UTC (permalink / raw)


"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:faqhpnFljnfU1@mid.individual.net...
> On 17-12-30 23:42 , Mehdi Saada wrote:
>> I have several questions more or less related.
>
>> First: why aspect DEFAULT_COMPONENT_VALUE can apply only
>> to components of scalar type ?
>
> Don't know. Perhaps the thought was that if the component is a record 
> type, then there is already a way to give default values to the components 
> of the record type.

Correct; we didn't want multiple ways of doing the same thing.

> However, the AARM explains that this is a representation attribute, and 
> why that is so, and (therefore?) requires the default component value to 
> be defined by a /static/ expression, which means that it can only be a 
> scalar or a string. In principle, a string might define the default 
> component value of an array with elements of a constrained String subtype, 
> but that is probably not a very common case.

Correct again. We did worry a bit about there not being a good way to set a 
default for an array of arrays, but we decided those aren't very common and 
the default can always be set for the ultimate (non-array) element type.

>> It would be nice to be able  to set a default value to an array type
>> in a generic package, equal to a generic object parameter.
>
> Agreed. Possibly this case was forgotten, or prevented by such a generic 
> object parameter not being a static value.

Not really. All of these defaults for for a *type*, not a subtype, so there 
is only one per type. (There are thorny semantic problems with per-subtype 
defaults, we decided they were not worth the trouble.) Thus, it wouldn't 
make sense to specify it for generic formal parameters, as presumably the 
actual type already has such a default (and if it doesn't, you can't add one 
in the generic unit).

                                         Randy.



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

* Re: formal array types and default values
  2018-01-03  0:52   ` Randy Brukardt
@ 2018-01-03  8:33     ` Niklas Holsti
  2018-01-03 20:53       ` Randy Brukardt
  0 siblings, 1 reply; 13+ messages in thread
From: Niklas Holsti @ 2018-01-03  8:33 UTC (permalink / raw)


On 18-01-03 02:52 , Randy Brukardt wrote:
> "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message
> news:faqhpnFljnfU1@mid.individual.net...
>> On 17-12-30 23:42 , Mehdi Saada wrote:
>>> I have several questions more or less related.

    [snip]

>>> It would be nice to be able  to set a default value to an array type
>>> in a generic package, equal to a generic object parameter.
>>
>> Agreed. Possibly this case was forgotten, or prevented by such a generic
>> object parameter not being a static value.
>
> Not really. All of these defaults for for a *type*, not a subtype, so there
> is only one per type. (There are thorny semantic problems with per-subtype
> defaults, we decided they were not worth the trouble.) Thus, it wouldn't
> make sense to specify it for generic formal parameters, as presumably the
> actual type already has such a default (and if it doesn't, you can't add one
> in the generic unit).

I think that Mehdi Saada wanted to be able to set a default value for 
the components of an ordinary (not formal generic) array type declared 
/in/ the generic package, using a formal generic object as the default 
value. For example:

    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).

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.

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").

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

* Re: formal array types and default values
  2017-12-30 21:42 formal array types and default values Mehdi Saada
  2017-12-30 22:20 ` Niklas Holsti
  2017-12-31 12:34 ` Jeffrey R. Carter
@ 2018-01-03 15:47 ` Mehdi Saada
  2018-01-03 21:16   ` Randy Brukardt
  2018-01-04 15:02 ` Mehdi Saada
  3 siblings, 1 reply; 13+ messages in thread
From: Mehdi Saada @ 2018-01-03 15:47 UTC (permalink / raw)


Let's make it a proposal for the next norm then. I'm half serious: depending on the difficulty, which I know nothing of, I am ok to help, however I can.
Such a nice (and logical) feature, would a shame not to do.


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

* Re: formal array types and default values
  2018-01-03  8:33     ` Niklas Holsti
@ 2018-01-03 20:53       ` Randy Brukardt
  2018-01-06  0:10         ` Niklas Holsti
  0 siblings, 1 reply; 13+ messages in thread
From: Randy Brukardt @ 2018-01-03 20:53 UTC (permalink / raw)


"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. 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. (Plus, there are some 
points where that wouldn't be sensible.) So I think we just gave up and 
required staticness. (But I might be totally mis-remembering this.)

> 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. Thus, if the client is defining the type, they have to define the 
defaults. 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.

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 most likely would have voted 
to kill them in that case, and I think others were leaning the same way.

> 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). :-)

In any case, a default value is a convinience feature; no one ought to be 
writing uninitialized object declarations in the first place. And the 
semantics of this is *very* complex in the general case (you want to remove 
both the staticness requirement and the scalar requirement). I don't think 
it is possibly worth the headaches.

                                           Randy.


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

* Re: formal array types and default values
  2018-01-03 15:47 ` Mehdi Saada
@ 2018-01-03 21:16   ` Randy Brukardt
  0 siblings, 0 replies; 13+ messages in thread
From: Randy Brukardt @ 2018-01-03 21:16 UTC (permalink / raw)


"Mehdi Saada" <00120260a@gmail.com> wrote in message 
news:5c75fcdd-c965-4d03-9161-3576212e674d@googlegroups.com...
> Let's make it a proposal for the next norm then. I'm half serious: 
> depending on the difficulty,
> which I know nothing of, I am ok to help, however I can.
> Such a nice (and logical) feature, would a shame not to do.

You mean a useless feature. :-)  (See my response to Niklas about the 
difficulty.)

The primary purpose of Default_Value is to detect errors. Specifically, most 
enumeration types have (or could have) a value that means Unknown or 
Uninitialized. For instance:

    type My_Color is (Unknown, Black, Red, Green, Blue, White)
        with Default_Value => Unknown;

With this declaration, any programming errors that fail to set an object of 
My_Color will show up as a value of "Unknown". Which can be reliably 
detected.

Other uses of default values are evil, because they hide an operation that 
should always be explicit. For instance:
     type Evil_Integer is new Integer
         with Default_Value => 0;

Since 0 is a legal, useful value of type Evil_Natural, some code might work 
by accident when an uninitialized object happened to get the right value by 
default. That sort of thing will not help future readers.

                                   Randy.



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

* Re: formal array types and default values
  2017-12-30 21:42 formal array types and default values Mehdi Saada
                   ` (2 preceding siblings ...)
  2018-01-03 15:47 ` Mehdi Saada
@ 2018-01-04 15:02 ` Mehdi Saada
  3 siblings, 0 replies; 13+ messages in thread
From: Mehdi Saada @ 2018-01-04 15:02 UTC (permalink / raw)


> Other uses of default values are evil, because they hide an operation that 
> should always be explicit. For instance: 
>     type Evil_Integer is new Integer 
>         with Default_Value => 0; 

> Since 0 is a legal, useful value of type Evil_Natural, some code might work by accident when an uninitialized object happened to get the right value by default.
Indeed, I can see it makes sense. Instead of default value it's better to provide a constructor method to the package's client.

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

* Re: formal array types and default values
  2018-01-03 20:53       ` Randy Brukardt
@ 2018-01-06  0:10         ` Niklas Holsti
  2018-01-08 21:12           ` Randy Brukardt
  0 siblings, 1 reply; 13+ messages in thread
From: Niklas Holsti @ 2018-01-06  0:10 UTC (permalink / raw)


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
       .      @       .


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

* Re: formal array types and default values
  2018-01-06  0:10         ` Niklas Holsti
@ 2018-01-08 21:12           ` Randy Brukardt
  0 siblings, 0 replies; 13+ messages in thread
From: Randy Brukardt @ 2018-01-08 21:12 UTC (permalink / raw)


"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:fbaifmFd3gjU1@mid.individual.net...
...
>> 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.

My recollection was that it was more that the expressions involved had to be 
very restricted in order to avoid problems (perhaps the problems were with 
freezing). The easiest way to do that was to make the items static.

BTW, if you want to follow all of the design issues that are recorded, you 
probably need to look at the meeting minutes as well as the AI. There is an 
index of meeting discussions on AIs found on the ARG Minutes page 
(http://www.ada-auth.org/arg-minutes.html).

                           Randy.


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

end of thread, other threads:[~2018-01-08 21:12 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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