comp.lang.ada
 help / color / mirror / Atom feed
* Discriminant of a limited type object
@ 2018-02-27 17:54 Dmitry A. Kazakov
  2018-02-27 22:20 ` Randy Brukardt
  0 siblings, 1 reply; 11+ messages in thread
From: Dmitry A. Kazakov @ 2018-02-27 17:54 UTC (permalink / raw)


Never needed that, but it seems that there no way to change the 
discriminant of a definite object of limited type because there is no 
assignment.

Say, we have an array of limited variant records with a defaulted 
discriminant. Then there is no way to fill that array ever, because 
element's discriminants are frozen.

P.S. Yet another example why Ada needs proper constructors instead of 
limited returns...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Discriminant of a limited type object
  2018-02-27 17:54 Discriminant of a limited type object Dmitry A. Kazakov
@ 2018-02-27 22:20 ` Randy Brukardt
  2018-02-27 22:53   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 11+ messages in thread
From: Randy Brukardt @ 2018-02-27 22:20 UTC (permalink / raw)


A defaulted discriminant for a limited type means just that: a default for 
the discriminant if the object is default initialized. It was always a 
mistake for Ada to tie that to mutability, but it doesn't matter for a 
limited type.

You can initialize an array of limited discriminanted objects with an 
aggregate of function calls (since those are built-in-place), and they can 
all have different discriminant values.

The "hole" is that you can't assign discriminants to tasks/protected objects 
easily, because there is no aggregate for them. You could use access-to-task 
to do that, but of course then you get the normal access type issues. 
Supposedly, you could use an aggregate iterator to do that, but I'm not sure 
how (perhaps there is a way with a nested record?)

                                  Randy.

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p745vr$pma$1@gioia.aioe.org...
> Never needed that, but it seems that there no way to change the 
> discriminant of a definite object of limited type because there is no 
> assignment.
>
> Say, we have an array of limited variant records with a defaulted 
> discriminant. Then there is no way to fill that array ever, because 
> element's discriminants are frozen.
>
> P.S. Yet another example why Ada needs proper constructors instead of 
> limited returns...
>
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de 



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

* Re: Discriminant of a limited type object
  2018-02-27 22:20 ` Randy Brukardt
@ 2018-02-27 22:53   ` Dmitry A. Kazakov
  2018-02-28  6:36     ` J-P. Rosen
  2018-02-28 23:10     ` Randy Brukardt
  0 siblings, 2 replies; 11+ messages in thread
From: Dmitry A. Kazakov @ 2018-02-27 22:53 UTC (permalink / raw)


On 2018-02-27 23:20, Randy Brukardt wrote:
> A defaulted discriminant for a limited type means just that: a default for
> the discriminant if the object is default initialized. It was always a
> mistake for Ada to tie that to mutability, but it doesn't matter for a
> limited type.
> 
> You can initialize an array of limited discriminanted objects with an
> aggregate of function calls (since those are built-in-place), and they can
> all have different discriminant values.

The problem is passing state between calls to the function. The code in 
mind is a loop over array elements. The loop body gutted and its parts 
moved into the function.

    A : T (1..N);
begin
    for Index in A'Range loop
       do-init of A (Index)
    end loop;

         |
         V

    Index : Positive := 1;
    function F return Element is
    begin
       Index := Index + 1;
       return do-init of A (Index - 1);
    end F;
    A : T (1..N) := (others => F)

Quite ugly. In the end I decided to flatten record variants and make the 
discriminant a plain record member. The memory loss is not big enough to 
justify the code above.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Discriminant of a limited type object
  2018-02-27 22:53   ` Dmitry A. Kazakov
@ 2018-02-28  6:36     ` J-P. Rosen
  2018-02-28  8:42       ` Dmitry A. Kazakov
  2018-02-28 17:16       ` Jeffrey R. Carter
  2018-02-28 23:10     ` Randy Brukardt
  1 sibling, 2 replies; 11+ messages in thread
From: J-P. Rosen @ 2018-02-28  6:36 UTC (permalink / raw)


Le 27/02/2018 à 23:53, Dmitry A. Kazakov a écrit :
>    A : T (1..N);
> begin
>    for Index in A'Range loop
>       do-init of A (Index)
>    end loop;
> 
>         |
>         V
> 
>    Index : Positive := 1;
>    function F return Element is
>    begin
>       Index := Index + 1;
>       return do-init of A (Index - 1);
>    end F;
>    A : T (1..N) := (others => F)
But this does not guarantee the order of components. I'd rather write
(changing do_init to a function):
   function Init_All (Size : Integer) return T is
   begin
      if Size = 1 then
         return (1 => do_init)
      else
         return do_init & Init_All (size - 1);
      end if;
   end;

   A : T := Init_All (N);
-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr


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

* Re: Discriminant of a limited type object
  2018-02-28  6:36     ` J-P. Rosen
@ 2018-02-28  8:42       ` Dmitry A. Kazakov
  2018-02-28  9:07         ` J-P. Rosen
  2018-02-28 17:16       ` Jeffrey R. Carter
  1 sibling, 1 reply; 11+ messages in thread
From: Dmitry A. Kazakov @ 2018-02-28  8:42 UTC (permalink / raw)


On 28/02/2018 07:36, J-P. Rosen wrote:
> Le 27/02/2018 à 23:53, Dmitry A. Kazakov a écrit :
>>     A : T (1..N);
>> begin
>>     for Index in A'Range loop
>>        do-init of A (Index)
>>     end loop;
>>
>>          |
>>          V
>>
>>     Index : Positive := 1;
>>     function F return Element is
>>     begin
>>        Index := Index + 1;
>>        return do-init of A (Index - 1);
>>     end F;
>>     A : T (1..N) := (others => F)
> But this does not guarantee the order of components. I'd rather write
> (changing do_init to a function):
>     function Init_All (Size : Integer) return T is
>     begin
>        if Size = 1 then
>           return (1 => do_init)
>        else
>           return do_init & Init_All (size - 1);
>        end if;
>     end;
> 
>     A : T := Init_All (N);

You are right, I forgot about the arbitrary order of initialization!

It was mad already. Recursion adds a new level of madness into it. 
(Provided GNAT would generate working the code at all. It has issues 
with limited return in much simpler cases.)

But it is still arbitrary order in "&" arguments. Though do_init could 
take as an argument N - Size + 1 in order to determine the element's 
index, any other external state is not guaranteed. E.g. initialization 
of A (I + 1) cannot depend on initialization of A (I).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Discriminant of a limited type object
  2018-02-28  8:42       ` Dmitry A. Kazakov
@ 2018-02-28  9:07         ` J-P. Rosen
  0 siblings, 0 replies; 11+ messages in thread
From: J-P. Rosen @ 2018-02-28  9:07 UTC (permalink / raw)


Le 28/02/2018 à 09:42, Dmitry A. Kazakov a écrit :
> But it is still arbitrary order in "&" arguments. Though do_init could
> take as an argument N - Size + 1 in order to determine the element's
> index, any other external state is not guaranteed. E.g. initialization
> of A (I + 1) cannot depend on initialization of A (I).
Well, the call order is arbitrary, however the build order is well
defined. So it matters only if the computation of some elements depends
on other elements being already computed. It if only depends on the
position, it's OK.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

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

* Re: Discriminant of a limited type object
  2018-02-28  6:36     ` J-P. Rosen
  2018-02-28  8:42       ` Dmitry A. Kazakov
@ 2018-02-28 17:16       ` Jeffrey R. Carter
  1 sibling, 0 replies; 11+ messages in thread
From: Jeffrey R. Carter @ 2018-02-28 17:16 UTC (permalink / raw)


On 02/28/2018 07:36 AM, J-P. Rosen wrote:
>     function Init_All (Size : Integer) return T is
>     begin
>        if Size = 1 then
>           return (1 => do_init)
>        else
>           return do_init & Init_All (size - 1);
>        end if;
>     end;

And I of course would write Init_All (0).

-- 
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28


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

* Re: Discriminant of a limited type object
  2018-02-27 22:53   ` Dmitry A. Kazakov
  2018-02-28  6:36     ` J-P. Rosen
@ 2018-02-28 23:10     ` Randy Brukardt
  2018-03-01  8:43       ` Dmitry A. Kazakov
  1 sibling, 1 reply; 11+ messages in thread
From: Randy Brukardt @ 2018-02-28 23:10 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p74nge$1oto$1@gioia.aioe.org...
...
> The problem is passing state between calls to the function. The code in 
> mind is a loop over array elements. The loop body gutted and its parts 
> moved into the function.
>
>    A : T (1..N);
> begin
>    for Index in A'Range loop
>       do-init of A (Index)
>    end loop;
>
>         |
>         V
>
>    Index : Positive := 1;
>    function F return Element is
>    begin
>       Index := Index + 1;
>       return do-init of A (Index - 1);
>    end F;
>    A : T (1..N) := (others => F)
>
> Quite ugly. In the end I decided to flatten record variants and make the 
> discriminant a plain record member. The memory loss is not big enough to 
> justify the code above.

Ada 2020 has you covered:

    function F(Index : Natural) return Element is
    begin
       return do-init of A (Index - 1);
    end F;
    A : T (1..N) := (for I in 1 .. N  => F(I));

Note the new iterator choice in the aggregate.

                                           Randy.




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

* Re: Discriminant of a limited type object
  2018-02-28 23:10     ` Randy Brukardt
@ 2018-03-01  8:43       ` Dmitry A. Kazakov
  2018-03-01 22:00         ` Randy Brukardt
  0 siblings, 1 reply; 11+ messages in thread
From: Dmitry A. Kazakov @ 2018-03-01  8:43 UTC (permalink / raw)


On 01/03/2018 00:10, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:p74nge$1oto$1@gioia.aioe.org...
> ...
>> The problem is passing state between calls to the function. The code in
>> mind is a loop over array elements. The loop body gutted and its parts
>> moved into the function.
>>
>>     A : T (1..N);
>> begin
>>     for Index in A'Range loop
>>        do-init of A (Index)
>>     end loop;
>>
>>          |
>>          V
>>
>>     Index : Positive := 1;
>>     function F return Element is
>>     begin
>>        Index := Index + 1;
>>        return do-init of A (Index - 1);
>>     end F;
>>     A : T (1..N) := (others => F)
>>
>> Quite ugly. In the end I decided to flatten record variants and make the
>> discriminant a plain record member. The memory loss is not big enough to
>> justify the code above.
> 
> Ada 2020 has you covered:
> 
>      function F(Index : Natural) return Element is
>      begin
>         return do-init of A (Index - 1);
>      end F;
>      A : T (1..N) := (for I in 1 .. N  => F(I));
> 
> Note the new iterator choice in the aggregate.

Definitely less ugly than recursion. But does this "loop" guarantee that 
F will be called in the order? Say we wanted read an array of limited 
elements from stream:

    function Read (Stream : not null access Root_Stream_Type'Class)
       return Element is
    begin
       return Result : Element (Length => Read (Stream)) do
          Read (Stream.all, Result.Text);
       end return;
    end F;
    A : T (1..N) := (for I in T'Range => Read (File'Access));

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Discriminant of a limited type object
  2018-03-01  8:43       ` Dmitry A. Kazakov
@ 2018-03-01 22:00         ` Randy Brukardt
  2018-03-02 10:30           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 11+ messages in thread
From: Randy Brukardt @ 2018-03-01 22:00 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:p78een$1jfi$1@gioia.aioe.org...
> On 01/03/2018 00:10, Randy Brukardt wrote:
...
>> Ada 2020 has you covered:
>>
>>      function F(Index : Natural) return Element is
>>      begin
>>         return do-init of A (Index - 1);
>>      end F;
>>      A : T (1..N) := (for I in 1 .. N  => F(I));
>>
>> Note the new iterator choice in the aggregate.
>
> Definitely less ugly than recursion. But does this "loop" guarantee that F 
> will be called in the order?

Nope, it's an aggregate and can be evaluated in any order. No aggregate is 
appropriate for something that has to be done sequentially. (With the 
exception of array delta aggregates; perhaps you could jury-rig something 
using one of them.)

It's not clear that there is much use for streaming of limited objects, as 
streaming is very much like assignment (it makes a copy of the object). One 
would expect that if assignment is a problem, so would streaming be a 
problem. I suppose there are some cases where controlled assignment isn't a 
good solution (I haven't seen one personally, but everything happens 
eventually...), but it seems like a niche need at best.

                                    Randy.


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

* Re: Discriminant of a limited type object
  2018-03-01 22:00         ` Randy Brukardt
@ 2018-03-02 10:30           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 11+ messages in thread
From: Dmitry A. Kazakov @ 2018-03-02 10:30 UTC (permalink / raw)


On 01/03/2018 23:00, Randy Brukardt wrote:

> It's not clear that there is much use for streaming of limited objects, as
> streaming is very much like assignment (it makes a copy of the object). One
> would expect that if assignment is a problem, so would streaming be a
> problem.

Assignment is a problem, construction is not. If streaming is a way to 
create a limited object that is OK, e.g. saving worker task state and 
restarting the task later in that state.

> I suppose there are some cases where controlled assignment isn't a
> good solution (I haven't seen one personally, but everything happens
> eventually...), but it seems like a niche need at best.

Controlled assignment? It is all OK if doubly-dispatching, otherwise it 
is a bug on many occasions.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

end of thread, other threads:[~2018-03-02 10:30 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-27 17:54 Discriminant of a limited type object Dmitry A. Kazakov
2018-02-27 22:20 ` Randy Brukardt
2018-02-27 22:53   ` Dmitry A. Kazakov
2018-02-28  6:36     ` J-P. Rosen
2018-02-28  8:42       ` Dmitry A. Kazakov
2018-02-28  9:07         ` J-P. Rosen
2018-02-28 17:16       ` Jeffrey R. Carter
2018-02-28 23:10     ` Randy Brukardt
2018-03-01  8:43       ` Dmitry A. Kazakov
2018-03-01 22:00         ` Randy Brukardt
2018-03-02 10:30           ` Dmitry A. Kazakov

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