* 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