comp.lang.ada
 help / color / mirror / Atom feed
* Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
@ 2020-11-01 18:41 Blady
  2020-11-03 11:05 ` Stephen Leake
  0 siblings, 1 reply; 7+ messages in thread
From: Blady @ 2020-11-01 18:41 UTC (permalink / raw)


Hello,

Let's take the following container with constant indexing for iteration:

      6.       type UXString is tagged private with
      7.          Constant_Indexing => Get,
      8.          Iterable          => (First => First, Next => Next, 
Has_Element => Has_Element, Element => Get);
      9.       function Make (Value : String) return UXString;
     10.       function Length (Self : UXString) return Natural;
     11.       function Get (Self : UXString; Index : Positive; 
Substitute : in Character) return Character;
     12.       function First (Self : UXString) return Positive is (1);
     13.       function Next (Self : UXString; Index : Positive) return 
Positive is (Index + 1);
     14.       function Has_Element (Self : UXString; Index : Positive) 
return Boolean is (Index <= Self.Length);

The Get constant indexing function has more than two parameters.
GNAT 2020 compilation is ok with the "for ... in ... loop" form:

     47.    for I in S1 loop
     48.       C := S3 (I, '@');
     49.       Put_Line (Character'pos (C)'img);
     50.    end loop;

  but not with the "for ... of ... loop" form (S2 and S3 loops):

     51.    for CC of S2 loop
     52.       C := CC;
     53.       F := CC = 'h';
     54.       Put_Line (Character'pos (C)'img & F'img);
     55.    end loop;
test_uxstrings_4.adb:51:17: error: missing argument for parameter 
"Substitute" in call to "Get" declared at line 11

     56.    for CC of S3 ('@') loop
     57.       C := CC;
     58.       F := CC = 'h';
     59.       Put_Line (Character'pos (C)'img & F'img);
     60.    end loop;
test_uxstrings_4.adb:56:14: error: container cannot be indexed with "A 
Character Type"

What is the correct usage?

Thanks, Pascal.


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

* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
  2020-11-01 18:41 Generalized Loop Iteration and User-Defined Indexing with more than two parameters Blady
@ 2020-11-03 11:05 ` Stephen Leake
  2020-11-06 15:39   ` Blady
  0 siblings, 1 reply; 7+ messages in thread
From: Stephen Leake @ 2020-11-03 11:05 UTC (permalink / raw)


Blady <p.p11@orange.fr> writes:

> Hello,
>
> Let's take the following container with constant indexing for iteration:
>
>      6.       type UXString is tagged private with
>      7.          Constant_Indexing => Get,
>      8.          Iterable          => (First => First, Next => Next,
> Has_Element => Has_Element, Element => Get);

>     11.       function Get (Self : UXString; Index : Positive;
> Substitute : in Character) return Character;

Hmm. Aspect "Iterable" is not defined by Ada. It is defined by GNAT. The
gnat reference manual says:

   * The value of `Element' is a primitive operation of the container
     type that takes both a container and a cursor and yields an
     `Element_Type', which must be a type declared in the container
     package or visible from it. For example:

    function Get_Element (Cont : Container; Position : Cursor) return Element_Type;

So it should have complained that your "Element => Get" is illegal.

> What is the correct usage?

An iterator 'Element' function can take only two parameters; the same is
true for standard Ada generalized iterators.

A Constant_Indexing function can take more than two parameters, but you
can only use it by indexing a container object directly (see LRM 4.1.6), 

A : UXString;

for Position in A.First .. A.Last loop

    Foo := A (Position, Substitute => 'C');
    ...
    
-- 
-- Stephe

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

* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
  2020-11-03 11:05 ` Stephen Leake
@ 2020-11-06 15:39   ` Blady
  2020-11-07  0:58     ` Randy Brukardt
  0 siblings, 1 reply; 7+ messages in thread
From: Blady @ 2020-11-06 15:39 UTC (permalink / raw)


Le 03/11/2020 à 12:05, Stephen Leake a écrit :
> Blady <p.p11@orange.fr> writes:
> 
>> Hello,
>>
>> Let's take the following container with constant indexing for iteration:
>>
>>       6.       type UXString is tagged private with
>>       7.          Constant_Indexing => Get,
>>       8.          Iterable          => (First => First, Next => Next,
>> Has_Element => Has_Element, Element => Get);
> 
>>      11.       function Get (Self : UXString; Index : Positive;
>> Substitute : in Character) return Character;
> 
> Hmm. Aspect "Iterable" is not defined by Ada. It is defined by GNAT. The
> gnat reference manual says:
> 
>     * The value of `Element' is a primitive operation of the container
>       type that takes both a container and a cursor and yields an
>       `Element_Type', which must be a type declared in the container
>       package or visible from it. For example:
> 
>      function Get_Element (Cont : Container; Position : Cursor) return Element_Type;
> 
> So it should have complained that your "Element => Get" is illegal.
> 
>> What is the correct usage?
> 
> An iterator 'Element' function can take only two parameters; the same is
> true for standard Ada generalized iterators.
> 
> A Constant_Indexing function can take more than two parameters, but you
> can only use it by indexing a container object directly (see LRM 4.1.6),
> 
> A : UXString;
> 
> for Position in A.First .. A.Last loop
> 
>      Foo := A (Position, Substitute => 'C');
>      ...

Hello,

Thanks Stephen, I hadn't noticed that Iterate aspect was a GNAT specific 
aspect. I've borrowed it from GNATColl XString type.

Thus, I turn my program in a more Ada way:

       type UXString is tagged private with
          Default_Iterator  => Iterate,
          Iterator_Element  => Character,
          Constant_Indexing => Get;
       type Cursor is private;
       function Get (Self : UXString; Position : Cursor) return Character;
       function Has_Element (Position : Cursor) return Boolean;
       package UXString_Iterators is new Ada.Iterator_Interfaces 
(Cursor, Has_Element);
       function Iterate (Self : UXString) return 
UXString_Iterators.Forward_Iterator'Class;
...
    for I in S1.Iterate loop
       C := S1 (I);
       F := S1 (I) = 'h';
       Put_Line (Character'pos (C)'img & F'img);
    end loop;
    for CC of S2 loop
       C := CC;
       Put_Line (Character'pos (C)'img);
    end loop;

Ada RM 5.5.1 "User-Defined Iterator Types" says:
"The Constant_Indexing aspect (if any) of an iterable container type T 
shall denote exactly one function with the following properties:
...
if there are more than two parameters, the additional parameters all 
have default expressions."
So I defines:
       function Get (Self : UXString; Position : Cursor; Substitute : in 
Character := '&') return Character;
and then:
    for I in S1.Iterate loop
       C := S1 (I, '@');
       F := S1 (I) = 'h';
       Put_Line (Character'pos (C)'img & F'img);
    end loop;
    for CC of S2 loop
       C := CC;
       Put_Line (Character'pos (C)'img);
    end loop;

However, I have 3 questions about iteration:
1) When using Default_Iterator aspect, both Iterator_Element and 
Constant_Indexing have to be defined also.
If I understand why Constant_Indexing at least has to be defined, what 
is the purpose of Iterator_Element?
2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal 
parameter instead of an abstract function of Forward_Iterator interface?
As:
    function Has_Element
      (Object   : Forward_Iterator;
       Position : Cursor) return Boolean is abstract;
The current way requires that Cursor type has the container reference 
embedded and cannot be a simple index type.
3) Couldn't be the additional parameters of the Constant_Indexing 
function without parameters defaults and a for ... of form as one of the 
followings?
       function Get (Self : UXString; Position : Cursor; Substitute : in 
Character) return Character;
...
for CC of S2 ('@') loop
       C := CC;
       Put_Line (Character'pos (C)'img);
    end loop;
or less preferable:
    for CC of S2 loop
       C := CC ('@');
       Put_Line (Character'pos (C)'img);
    end loop;

Thanks for your answers, Pascal.

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

* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
  2020-11-06 15:39   ` Blady
@ 2020-11-07  0:58     ` Randy Brukardt
  2020-11-07 17:46       ` Blady
  2020-11-07 23:54       ` Stephen Leake
  0 siblings, 2 replies; 7+ messages in thread
From: Randy Brukardt @ 2020-11-07  0:58 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3487 bytes --]

"Blady" <p.p11@orange.fr> wrote in message 
news:ro3qms$1vdh$1@gioia.aioe.org...
> Le 03/11/2020 à 12:05, Stephen Leake a écrit :
...
> Ada RM 5.5.1 "User-Defined Iterator Types" says:
> "The Constant_Indexing aspect (if any) of an iterable container type T 
> shall denote exactly one function with the following properties:
> ...
> if there are more than two parameters, the additional parameters all have 
> default expressions."
> So I defines:
>       function Get (Self : UXString; Position : Cursor; Substitute : in 
> Character := '&') return Character;
> and then:
>    for I in S1.Iterate loop
>       C := S1 (I, '@');
>       F := S1 (I) = 'h';
>       Put_Line (Character'pos (C)'img & F'img);
>    end loop;
>    for CC of S2 loop
>       C := CC;
>       Put_Line (Character'pos (C)'img);
>    end loop;
>
> However, I have 3 questions about iteration:
> 1) When using Default_Iterator aspect, both Iterator_Element and 
> Constant_Indexing have to be defined also.
> If I understand why Constant_Indexing at least has to be defined, what is 
> the purpose of Iterator_Element?

Iterator functions work on cursors. The "of" form works on elements. In 
order to figure out what constant indexing function to use in the element 
iterator, we need to know both the parameter and result types. (Remember 
that there can be many overloaded indexing functions, you're not restricted 
to a single function [just a single name].)

> 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal 
> parameter instead of an abstract function of Forward_Iterator interface?
> As:
>    function Has_Element
>      (Object   : Forward_Iterator;
>       Position : Cursor) return Boolean is abstract;
> The current way requires that Cursor type has the container reference 
> embedded and cannot be a simple index type.

I suppose other designs could have been chosen. The generic one was the 
original proposal; probably the person that designed it doesn't use 
interfaces very much. (I think that was me. ;-). If I recall correctly, the 
original interface design didn't work at all, and the generic was a fix. But 
I don't remember any of the details anymore (could look them up, but would 
need more motivation for that :-).

> 3) Couldn't be the additional parameters of the Constant_Indexing function 
> without parameters defaults and a for ... of form as one of the 
> followings?
>       function Get (Self : UXString; Position : Cursor; Substitute : in 
> Character) return Character;
> ...
> for CC of S2 ('@') loop
>       C := CC;
>       Put_Line (Character'pos (C)'img);
>    end loop;
> or less preferable:
>    for CC of S2 loop
>       C := CC ('@');
>       Put_Line (Character'pos (C)'img);
>    end loop;

I suppose, but that sort of thing would substantially complicate the 
mechanism, especially resolution.

Personally, I think of the "of" form of iterators as a convinient shorthand 
to be used only in limited circumstances. The cursor form ("in"), the more 
traditional form, should be used when you have more complex needs. For 
instance, for the above:

    for CC in S2.Iterator loop
      C := S2(CC, '@');
      Put_Line (Character'pos (C)'img);
   end loop;

Trying to jam everything into the shorthand just complicates the 
implementation and makes it a lot harder for the reader.

                        Randy.





> Thanks for your answers, Pascal. 


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

* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
  2020-11-07  0:58     ` Randy Brukardt
@ 2020-11-07 17:46       ` Blady
  2020-11-10  1:45         ` Randy Brukardt
  2020-11-07 23:54       ` Stephen Leake
  1 sibling, 1 reply; 7+ messages in thread
From: Blady @ 2020-11-07 17:46 UTC (permalink / raw)


Le 07/11/2020 à 01:58, Randy Brukardt a écrit :
> "Blady" <p.p11@orange.fr> wrote in message
>> Le 03/11/2020 à 12:05, Stephen Leake a écrit :
> ...
>> Ada RM 5.5.1 "User-Defined Iterator Types" says:
>> "The Constant_Indexing aspect (if any) of an iterable container type T
>> shall denote exactly one function with the following properties:
>> ...
>> if there are more than two parameters, the additional parameters all have
>> default expressions."
>> So I defines:
>>        function Get (Self : UXString; Position : Cursor; Substitute : in
>> Character := '&') return Character;
>> and then:
>>     for I in S1.Iterate loop
>>        C := S1 (I, '@');
>>        F := S1 (I) = 'h';
>>        Put_Line (Character'pos (C)'img & F'img);
>>     end loop;
>>     for CC of S2 loop
>>        C := CC;
>>        Put_Line (Character'pos (C)'img);
>>     end loop;
>>
>> However, I have 3 questions about iteration:
>> 1) When using Default_Iterator aspect, both Iterator_Element and
>> Constant_Indexing have to be defined also.
>> If I understand why Constant_Indexing at least has to be defined, what is
>> the purpose of Iterator_Element?
> 
> Iterator functions work on cursors. The "of" form works on elements. In
> order to figure out what constant indexing function to use in the element
> iterator, we need to know both the parameter and result types. (Remember
> that there can be many overloaded indexing functions, you're not restricted
> to a single function [just a single name].)

Thanks for clarification, I get it now. IMHO this clearly reduces the 
possibilities of the "for ... of ... loop" form to only one driven by 
Iterator_Element aspect. We might imagine iterate on a container on more 
than one its attributes. Let's iterate for instance on a collection of 
cars (Car_Coll) with different brands (Brand) and colors (Color):
CC1, CC2 : Car_Coll;
...
for B : Brand of CC1 loop
-- iterate on the car brands present inside CC1
...
for C : Color of CC2 loop
-- iterate on the car colors present inside CC2
...
if Iterator_Element is set to Color for example then the following code 
is equivalent to the previous one:
for C of CC2 loop
-- iterate on the car colors present inside CC2
...
If Iterator_Element is not set then the type in the loop must be provided.
The indexing function would be then chosen either by Iterator_Element 
(by default) or overridden by the type given in the loop.
Do this would help someone? Probably not a lot but I would give more 
symmetry between two for loop forms.

> 
>> 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal
>> parameter instead of an abstract function of Forward_Iterator interface?
>> As:
>>     function Has_Element
>>       (Object   : Forward_Iterator;
>>        Position : Cursor) return Boolean is abstract;
>> The current way requires that Cursor type has the container reference
>> embedded and cannot be a simple index type.
> 
> I suppose other designs could have been chosen. The generic one was the
> original proposal; probably the person that designed it doesn't use
> interfaces very much. (I think that was me. ;-). If I recall correctly, the
> original interface design didn't work at all, and the generic was a fix. But
> I don't remember any of the details anymore (could look them up, but would
> need more motivation for that :-).

Does a message on Ada Comments could help ;-)?

>> 3) Couldn't be the additional parameters of the Constant_Indexing function
>> without parameters defaults and a for ... of form as one of the
>> followings?
>>        function Get (Self : UXString; Position : Cursor; Substitute : in
>> Character) return Character;
>> ...
>> for CC of S2 ('@') loop
>>        C := CC;
>>        Put_Line (Character'pos (C)'img);
>>     end loop;
>> or less preferable:
>>     for CC of S2 loop
>>        C := CC ('@');
>>        Put_Line (Character'pos (C)'img);
>>     end loop;
> 
> I suppose, but that sort of thing would substantially complicate the
> mechanism, especially resolution.
> 
> Personally, I think of the "of" form of iterators as a convinient shorthand
> to be used only in limited circumstances. The cursor form ("in"), the more
> traditional form, should be used when you have more complex needs. For
> instance, for the above:
> 
>      for CC in S2.Iterator loop
>        C := S2(CC, '@');
>        Put_Line (Character'pos (C)'img);
>     end loop;
> 
> Trying to jam everything into the shorthand just complicates the
> implementation and makes it a lot harder for the reader.

This is connected to point 1):
Do this would help someone? Probably not a lot but I would give more 
symmetry between two for loop forms.

>                          Randy

Thanks Randy for your answers, Pascal.

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

* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
  2020-11-07  0:58     ` Randy Brukardt
  2020-11-07 17:46       ` Blady
@ 2020-11-07 23:54       ` Stephen Leake
  1 sibling, 0 replies; 7+ messages in thread
From: Stephen Leake @ 2020-11-07 23:54 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Blady" <p.p11@orange.fr> wrote in message 
> news:ro3qms$1vdh$1@gioia.aioe.org...
>
>> 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal 
>> parameter instead of an abstract function of Forward_Iterator interface?
>> As:
>>    function Has_Element
>>      (Object   : Forward_Iterator;
>>       Position : Cursor) return Boolean is abstract;
>> The current way requires that Cursor type has the container reference 
>> embedded and cannot be a simple index type.
>
> I suppose other designs could have been chosen. 

In addition, you can store the container reference in your Iterator object.


-- 
-- Stephe

Written from unceded ancestral homelands of the Huichiun, an Ohlone
people,for which I pay Shuumi Land Tax

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

* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters.
  2020-11-07 17:46       ` Blady
@ 2020-11-10  1:45         ` Randy Brukardt
  0 siblings, 0 replies; 7+ messages in thread
From: Randy Brukardt @ 2020-11-10  1:45 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1018 bytes --]

"Blady" <p.p11@orange.fr> wrote in message 
news:ro6mhg$1lmd$1@gioia.aioe.org...
> Le 07/11/2020 à 01:58, Randy Brukardt a écrit :
...
>> I suppose other designs could have been chosen. The generic one was the
>> original proposal; probably the person that designed it doesn't use
>> interfaces very much. (I think that was me. ;-). If I recall correctly, 
>> the
>> original interface design didn't work at all, and the generic was a fix. 
>> But
>> I don't remember any of the details anymore (could look them up, but 
>> would
>> need more motivation for that :-).
>
> Does a message on Ada Comments could help ;-)?

I rather doubt a new design would be introduced, simply because it would be 
very complex to have multiple approaches working at the same time, and the 
problems with the existing design aren't as significant as many other things 
that could be fixed with Ada. (There's always a limited amount of effort 
that can be expended.)

                                     Randy.


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

end of thread, other threads:[~2020-11-10  1:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-01 18:41 Generalized Loop Iteration and User-Defined Indexing with more than two parameters Blady
2020-11-03 11:05 ` Stephen Leake
2020-11-06 15:39   ` Blady
2020-11-07  0:58     ` Randy Brukardt
2020-11-07 17:46       ` Blady
2020-11-10  1:45         ` Randy Brukardt
2020-11-07 23:54       ` Stephen Leake

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