comp.lang.ada
 help / color / mirror / Atom feed
* Iterable container as generic parameter
@ 2018-01-25  0:22 Lionel Draghi
  2018-01-25  3:36 ` Randy Brukardt
  2018-01-26 23:07 ` Lionel Draghi
  0 siblings, 2 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-25  0:22 UTC (permalink / raw)


I would like to make a generic function containing this simple code :

for E of L loop
   Put_Line (Image (E));
end loop;

And I would like to have this generic compatible with all "iterable container".

I thought it would be possible by just providing as generic parameters the Image function, and an Ada.Iterator_Interfaces instantiation, but without referencing the container.
Isn't the iterator supposed to encapsulates both the cursor and the container?

Something like : 

generic
   type Cursor is (<>);
   with function Image (C : Cursor) return String;
   with package Iterator_Interfaces is 
     new Ada.Iterator_Interfaces (Cursor, others => <>); 
function List_Image return String;

But I couldn't figure out a simple way to do the body :
1. using the "for E of L" or the "for C in L.Iterate" loop refers to L, the Iterable container : why should I need that here? 

2. and it's not clear for me how to directly use a Cursor with First and Next functions provided by Iterator_Interfaces, that need a Forward_Iterator parameter.

Any hints?

Thanks,

-- 
-- Lionel


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

* Re: Iterable container as generic parameter
  2018-01-25  0:22 Iterable container as generic parameter Lionel Draghi
@ 2018-01-25  3:36 ` Randy Brukardt
  2018-01-25 14:58   ` Lionel Draghi
  2018-01-26 23:07 ` Lionel Draghi
  1 sibling, 1 reply; 19+ messages in thread
From: Randy Brukardt @ 2018-01-25  3:36 UTC (permalink / raw)


"Lionel Draghi" <lionel.draghi@gmail.com> wrote in message 
news:61ba3677-0041-4dba-af9b-a5df48f3ce8a@googlegroups.com...
>I would like to make a generic function containing this simple code :
>
> for E of L loop
>   Put_Line (Image (E));
> end loop;
>
> And I would like to have this generic compatible with all "iterable 
> container".
>
> I thought it would be possible by just providing as generic parameters the 
> Image function, and an Ada.Iterator_Interfaces instantiation, but without 
> referencing the container.
> Isn't the iterator supposed to encapsulates both the cursor and the 
> container?
>
> Something like :
>
> generic
>   type Cursor is (<>);
>   with function Image (C : Cursor) return String;
>   with package Iterator_Interfaces is
>     new Ada.Iterator_Interfaces (Cursor, others => <>);
> function List_Image return String;
>
> But I couldn't figure out a simple way to do the body :
> 1. using the "for E of L" or the "for C in L.Iterate" loop refers to L, 
> the Iterable container : why should I need that here?

L is the container object that you are iterating over. An iterator interface 
describes *how* to iterate, but you also have to describe *what* data to 
iterate.

> 2. and it's not clear for me how to directly use a Cursor with First and 
> Next functions provided by Iterator_Interfaces, that need a 
> Forward_Iterator parameter.

You just call it, prefixing with the container object in question. These are 
just functions that work like any other functions.

---

As to the question you didn't ask, you clearly need the container type 
somewhere in your interface, so you can pass container objects. (Or, I 
suppose, you could reference the type used in the instance of the 
Iterator_Interfaces.) Otherwise, you just have methods but no data. And 
there isn't anything interesting that you can do with just methods!

                                    Randy.


>
> Any hints?
>
> Thanks,
>
> -- 
> -- Lionel 


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

* Re: Iterable container as generic parameter
  2018-01-25  3:36 ` Randy Brukardt
@ 2018-01-25 14:58   ` Lionel Draghi
  2018-01-25 18:26     ` briot.emmanuel
  2018-01-26  4:50     ` Randy Brukardt
  0 siblings, 2 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-25 14:58 UTC (permalink / raw)


> As to the question you didn't ask, you clearly need the container type 
> somewhere in your interface, so you can pass container objects. (Or, I 
> suppose, you could reference the type used in the instance of the 
> Iterator_Interfaces.) Otherwise, you just have methods but no data. And 
> there isn't anything interesting that you can do with just methods!
> 
>                                     Randy.

Thanks Randy for the answer, this is actually my question.
And what you put into parenthesis was what I was trying to do.

Here is my point : 
If I limit the procedure scope to a specific container, the generic is simple : 

with Ada.Containers.Doubly_Linked_Lists;
generic
   type Element_Type is (<>);
   with function Image (Element : Element_Type) return String is <>;
   with package Lists is new Ada.Containers.Doubly_Linked_Lists (Element_Type);
function List_Image_1 (List : Lists.List) return string;

But if want something that could be used with both Lists and Maps, I have to provide much more parameters : 

with Ada.Containers;
generic
   type Element_Type (<>) is Private;
   with function Image (Element : Element_Type) return String is <>;

   type Cursor is private; 
   with function First return Cursor is <>;
   with function Next (Position : Cursor) return Cursor is <>;
   with function Length return Ada.Containers.Count_Type is <>;

   with function Element (Position : Cursor) return Element_Type is <>;

function List_Image_2 return String;

And that sounds a bit to complex to me, because what I am doing is just creating my own iterator. 
This is why I was trying to simplify the generic formal part by using the Iterator_Interfaces.

I have the feeling that I’m missing something.

Lionel

PS : here is my test code.

with Ada.Containers.Doubly_Linked_Lists;

generic
   type Element_Type is (<>);
   with function Image (Element : Element_Type) return String is <>;
   with package Lists is new Ada.Containers.Doubly_Linked_Lists (Element_Type);

function List_Image_1 (List : Lists.List) return string;

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; 

function List_Image_1 (List : Lists.List) return String is
   Tmp : Unbounded_String;
begin
   for E of List loop
      Tmp := Tmp & " " & Image (E);
   end loop;
   return To_String (Tmp);
end List_Image_1;

with Ada.Containers;

generic
   type Element_Type (<>) is Private;
   with function Image (Element : Element_Type) return String is <>;

   type Cursor is private; 
   with function First return Cursor is <>;
   with function Next (Position : Cursor) return Cursor is <>;
   with function Length return Ada.Containers.Count_Type is <>;
   
   with function Element (Position : Cursor) return Element_Type is <>;
   
function List_Image_2 return String;

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

function List_Image_2 return String is
   Tmp : Unbounded_String;
   C   : Cursor;
begin
   -- a bit more sophisticated format
   case Length is 
      when 0 => return "";
      when 1 => return "[" & Image (Element (First)) & "]";
      when others => 
         C := First;
         Tmp := To_Unbounded_String ("[") & Image (Element (C));
         for I in 2 .. Length loop
            C := Next (C);
            Tmp := Tmp  & ", " & Image (Element (C));
         end loop;
         Tmp := Tmp & "]";
   end case;
   return To_String (Tmp);
end List_Image_2;

with List_Image_1;
with List_Image_2;

with Ada.Containers.Doubly_Linked_Lists;
with Ada.Containers.Indefinite_Hashed_Sets;
with Ada.Strings.Hash_Case_Insensitive;

with Ada.Text_Io;

procedure Test_List_Image is
   
   -- container for test purposes
   package Integer_Lists is new Ada.Containers.Doubly_Linked_Lists (Integer);
   List : Integer_Lists.List;

   Function Integer_List_Image_1 is new List_Image_1 
     (Integer, 
      Integer'Image, 
      Integer_Lists);

   function Integer_List_Image_2 is new List_Image_2 
     (Integer, 
      Integer'Image, 
      Integer_Lists.Cursor,
      List.First,
      Integer_Lists.Next,
      List.Length,
      Integer_Lists.Element);

   -- another container 
   function Image (S : String) return String is (String (S));
   
   package Id_Sets is new Ada.Containers.Indefinite_Hashed_Sets 
     (String, Ada.Strings.Hash_Case_Insensitive, "=");
   Set : Id_Sets.Set;
   use Id_Sets; 
   
   function Id_Set_Image_2 is new List_Image_2 
     (String, 
      Image, 
      Cursor  => Id_Sets.Cursor,
      First   => Set.First,
      Next    => Id_Sets.Next,
      Length  => Set.Length,
      Element => Id_Sets.Element);

begin
   -- ----------------------------------------------------------------------
   Ada.Text_Io.Put_Line ("Test generic 1 on a list :");
   Ada.Text_Io.Put_Line (Integer_List_Image_1 (List));

   List.Append (1);
   Ada.Text_Io.Put_Line (Integer_List_Image_1 (List));

   List.Append (2);
   Ada.Text_Io.Put_Line (Integer_List_Image_1 (List));

   List.Append (3);
   Ada.Text_Io.Put_Line (Integer_List_Image_1 (List));
   Ada.Text_Io.New_Line;
   
   -- ----------------------------------------------------------------------
   Ada.Text_Io.Put_Line ("Test generic 2 on a list :");

   List.Clear;
   Ada.Text_Io.Put_Line (Integer_List_Image_2);

   List.Append (1);
   Ada.Text_Io.Put_Line (Integer_List_Image_2);

   List.Append (2);
   Ada.Text_Io.Put_Line (Integer_List_Image_2);

   List.Append (3);
   Ada.Text_Io.Put_Line (Integer_List_Image_2);
   Ada.Text_Io.New_Line;

   -- ----------------------------------------------------------------------
   Ada.Text_Io.Put_Line ("Test generic 2 on a set :");
   
   Ada.Text_Io.Put_Line (Id_Set_Image_2);
   Set.Insert ("Hyperion");
   
   Ada.Text_Io.Put_Line (Id_Set_Image_2);
   Set.Insert ("Endymion");
   
   Ada.Text_Io.Put_Line (Id_Set_Image_2);
   Set.Insert ("TechnoCore");

   Ada.Text_Io.Put_Line (Id_Set_Image_2);

end Test_List_Image;


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

* Re: Iterable container as generic parameter
  2018-01-25 14:58   ` Lionel Draghi
@ 2018-01-25 18:26     ` briot.emmanuel
  2018-01-26  4:50     ` Randy Brukardt
  1 sibling, 0 replies; 19+ messages in thread
From: briot.emmanuel @ 2018-01-25 18:26 UTC (permalink / raw)


Lionel,
This won't provide an answer to your specific question (I also haven't been able to achieve that). Some ideas that you might find interesting.
I have spent some time last year working on "traits containers" (https://github.com/AdaCore/ada-traits-containers for some code). The idea is to split the large set of formal parameters you showed in your example into several smaller sets, which are then passed via a signature package (aka traits).

For instance, to implement your List_Item, we need to know a few things on the container (but not its specific type), and how to iterate. To create the container, we need to know what elements it stores. This could lead to the following (untested) signature packages:

      generic
            type T (<>) is limited private;
            type Stored_T is private;
            with function Store (E : T) return Stored_T;
            with function Retrieve (E : Stored_T) return T;
      package Elements is
      end Elements;
      --  How to store elements in a data structure. If T is definite, we simply copy, but if
      --  if is indefinite, we need to allocate memory for instance.

      generic
            with package Elems is new Elements (<>);
            type Iterable (<>) is limited private;
            type Cursor is private;
            with function First (Self : Iterable) return Cursor;
            with function Next (C : Cursor) return Cursor;
            with function Get (C : Cursor) return Elems.T;
      package Iterables is
      end Iterables;

      generic
           with package Iterable is new Iterables (<>);
            --  A container is an iterable data structure, that we can also modify

           with procedure Append (Self : in out Iterable.Iterable; E : Iterable.Elems.T);
      package Containers is
            subtype Container is Iterable.Iterable;
      end Containers;

Then if you create a specific container type (or wrap one of the predefined Ada containers), you provide an instance of those predefined packages when applicable. As shown above, although the signature packages themselves should contain any code, they can provide instances for other signature packages (think: in C++, a random-access cursor is also a forward cursor).

Finally, your algorithm is generic in terms of those generic packages:

      generic
           with package Iterable is new Iterables (<>);
      function Image (Self : Iterable.Iterable) return String;

It receives an object, for which it knows how to create a cursor and manipulate that cursor. The instances of the signature packages we created above are bricks, and your algorithm works in terms of those bricks.

This is a promising scheme. In fact, the more such elementary bricks you have (one to describe how to store elements in other data structure, one to describe iterables, one to describe hashables, ...) the more interesting it becomes, since you can combine them in unexpected ways.

BUT: my containers were using the GNAT 'Iterable' aspect, not the more complex Ada iterators, and I did not find a way to describe via the generic parameters that a "for..of" loop would work on them. 

This is related to your question, but unfortunately (and sorry) does not provide a solution.

Emmanuel


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

* Re: Iterable container as generic parameter
  2018-01-25 14:58   ` Lionel Draghi
  2018-01-25 18:26     ` briot.emmanuel
@ 2018-01-26  4:50     ` Randy Brukardt
  2018-01-26  9:09       ` briot.emmanuel
  1 sibling, 1 reply; 19+ messages in thread
From: Randy Brukardt @ 2018-01-26  4:50 UTC (permalink / raw)


"Lionel Draghi" <lionel.draghi@gmail.com> wrote in message 
news:6427a793-91a4-4feb-b067-ed89b4c04421@googlegroups.com...
>> As to the question you didn't ask, you clearly need the container type
>> somewhere in your interface, so you can pass container objects. (Or, I
>> suppose, you could reference the type used in the instance of the
>> Iterator_Interfaces.) Otherwise, you just have methods but no data. And
>> there isn't anything interesting that you can do with just methods!
>
>Thanks Randy for the answer, this is actually my question.
>And what you put into parenthesis was what I was trying to do.

Formal package parameters that are given by <> are available inside the 
generic unit given their formal names.

But now looking at the definition, I see the container type isn't in that 
signature.

>Here is my point :
>If I limit the procedure scope to a specific container, the generic is 
>simple :
...
>But if want something that could be used with both Lists and Maps, I have 
>to provide much more parameters :

...

Emmanuel already described using signature packages for this.

But I probably would just use your original spec and add the container type 
and iterator function, something like:

generic
   type Cursor is (<>);
   with function Image (C : Cursor) return String;
   type Container (<>) is private;
   with package Iterator_Interfaces is
     new Ada.Iterator_Interfaces (Cursor, others => <>);
   with function Iterator (C : Container) return 
Iterator_Interfaces.Forward_Iterator'Class;
function List_Image return String;

Not sure if this is enough (I have work to do tonight!), but this is where 
I'd start.

                              Randy.


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

* Re: Iterable container as generic parameter
  2018-01-26  4:50     ` Randy Brukardt
@ 2018-01-26  9:09       ` briot.emmanuel
  2018-01-26 22:32         ` Lionel Draghi
  2018-01-28 18:08         ` Lionel Draghi
  0 siblings, 2 replies; 19+ messages in thread
From: briot.emmanuel @ 2018-01-26  9:09 UTC (permalink / raw)


> But I probably would just use your original spec and add the container type 
> and iterator function, something like:
> 
> generic
>    type Cursor is (<>);
>    with function Image (C : Cursor) return String;
>    type Container (<>) is private;
>    with package Iterator_Interfaces is
>      new Ada.Iterator_Interfaces (Cursor, others => <>);
>    with function Iterator (C : Container) return 
> Iterator_Interfaces.Forward_Iterator'Class;
> function List_Image return String;
> 

I think that's a good starting point.
When this works, and if you have a similar need for another algorithm, then you can start thinking of signature packages and introduce some of them.

I started my work on the traits containers when I wanted to write algorithms that would work for any of the standard containers (later on I realized that those containers, at least in the GNAT implementation) had a lot of duplicate code between definite/indefinite variants, that could be factored away with an Elements traits package, so I introduced that. And so on.

I definitely agree with Randy here that we should not construct signature packages in the abstract, but start from existing and working code.

The only drawback is that introducing them breaks the existing API:
    - instantiating the generic now uses different set of formals.
       We have proposed http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0205-1.txt?rev=1.2&raw=N for the next revision of the language, which might help a little

   - moving out some code out of an existing package and into a generic means you need to introduce a lot of renamings to preserve existing API.
      We have proposed http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0229-1.txt?rev=1.3&raw=N to help.

I recently made changes to GNATCOLL so that people could chose which kind of reference counting they want to use for GNATCOLL.Strings. Either no counter (in which case we don't do copy-on-write), non-atomic counters or atomic counters. This could only be done via a signature package, since declaring a type with aspect "Atomic" generates some memory fence operations which are slow. That leads to a 3 to 4% speed improvement. Just another example of possible signature package.

Emmanuel


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

* Re: Iterable container as generic parameter
  2018-01-26  9:09       ` briot.emmanuel
@ 2018-01-26 22:32         ` Lionel Draghi
  2018-01-27  7:03           ` Randy Brukardt
  2018-01-28 18:08         ` Lionel Draghi
  1 sibling, 1 reply; 19+ messages in thread
From: Lionel Draghi @ 2018-01-26 22:32 UTC (permalink / raw)


Thank you both for all this, it gave me food for thought.

I moved forward using signature package on the format aspect of my list.

I want my generic to be able to print the same list this way :
[A, B, C] 
or this way :
- A
- B
- C

So I exported the Format aspects to a List_Format signature generic.

generic
   Prefix    : String := "";
   Postfix   : String := "";
   Separator : String := "";
   -- etc.
package List_Format is end; 

And I created some predefined variant : 

package Bracketed_List_Format is new List_Format (Prefix    => "[",
                                                  Postfix   => "]",
                                                  Separator => ", ");

It's now the last formal parameter of List_Image :

(current implementation, I have note yet taken into account Randy last suggestion)

generic
   type Element_Type (<>) is Private;
   with function Image (Element : Element_Type) return String is <>;

   type Cursor is private;
   with function First return Cursor is <>;
   with function Next (Position : Cursor) return Cursor is <>;
   with function Length return Ada.Containers.Count_Type is <>;

   with function Element (Position : Cursor) return Element_Type is <>;

   with package Format is new List_Format (<>);

function List_Image return String;

The current List_Image generic has 7 formal parameters.
Adding the printing options is about 8 more formal parameters, that a lot for a typical use.  

The code is functionally close to what I want as a first version, I will now try to ease the use (the instantiation) by "defaulting" as much as possible formal parameters.

By the way, I have another question. There is no way to provide a default instantiation to a formal package parameter?

I would like to do something like :

   with package Format is new List_Format := Bracketed_List_Format;
                                         -------------------------
  

Lionel 


Le 26/01/2018 à 10:09, ...emmanuel... a écrit :
>> But I probably would just use your original spec and add the container type
>> and iterator function, something like:
>>
>> generic
>>     type Cursor is (<>);
>>     with function Image (C : Cursor) return String;
>>     type Container (<>) is private;
>>     with package Iterator_Interfaces is
>>       new Ada.Iterator_Interfaces (Cursor, others => <>);
>>     with function Iterator (C : Container) return
>> Iterator_Interfaces.Forward_Iterator'Class;
>> function List_Image return String;
>>
> 
> I think that's a good starting point.
> When this works, and if you have a similar need for another algorithm, then you can start thinking of signature packages and introduce some of them.
> 
> I started my work on the traits containers when I wanted to write algorithms that would work for any of the standard containers (later on I realized that those containers, at least in the GNAT implementation) had a lot of duplicate code between definite/indefinite variants, that could be factored away with an Elements traits package, so I introduced that. And so on.
> 
> I definitely agree with Randy here that we should not construct signature packages in the abstract, but start from existing and working code.
> 
> The only drawback is that introducing them breaks the existing API:
>      - instantiating the generic now uses different set of formals.
>         We have proposed http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0205-1.txt?rev=1.2&raw=N for the next revision of the language, which might help a little
> 
>     - moving out some code out of an existing package and into a generic means you need to introduce a lot of renamings to preserve existing API.
>        We have proposed http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0229-1.txt?rev=1.3&raw=N to help.
> 
> I recently made changes to GNATCOLL so that people could chose which kind of reference counting they want to use for GNATCOLL.Strings. Either no counter (in which case we don't do copy-on-write), non-atomic counters or atomic counters. This could only be done via a signature package, since declaring a type with aspect "Atomic" generates some memory fence operations which are slow. That leads to a 3 to 4% speed improvement. Just another example of possible signature package.
> 
> Emmanuel
> 

-- 
-- Lionel

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

* Re: Iterable container as generic parameter
  2018-01-25  0:22 Iterable container as generic parameter Lionel Draghi
  2018-01-25  3:36 ` Randy Brukardt
@ 2018-01-26 23:07 ` Lionel Draghi
  1 sibling, 0 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-26 23:07 UTC (permalink / raw)


You can download the v0.0.0 here :
https://github.com/LionelDraghi/List_Image

And :
> make

Lionel

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

* Re: Iterable container as generic parameter
  2018-01-26 22:32         ` Lionel Draghi
@ 2018-01-27  7:03           ` Randy Brukardt
  2018-01-27 11:38             ` Lionel Draghi
  0 siblings, 1 reply; 19+ messages in thread
From: Randy Brukardt @ 2018-01-27  7:03 UTC (permalink / raw)


"Lionel Draghi" <lionel.draghi@gmail.com> wrote in message 
news:36f3a79b-0db5-4199-9a7a-cbf64058cd18@googlegroups.com...
...
>By the way, I have another question. There is no way to provide a default
> instantiation to a formal package parameter?

Not in Ada 2012 or before. There is an open issue (it is one of those that 
Emmanuel referenced in his message) to allow that. It hasn't progressed any 
significant amount at this time.

(Aside: There are a LOT of ideas submitted for Ada 2020. Many good ideas are 
likely to be left out simply because of lack of time and/or too much 
change.)

                           Randy.


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

* Re: Iterable container as generic parameter
  2018-01-27  7:03           ` Randy Brukardt
@ 2018-01-27 11:38             ` Lionel Draghi
  2018-01-27 14:31               ` Jere
  0 siblings, 1 reply; 19+ messages in thread
From: Lionel Draghi @ 2018-01-27 11:38 UTC (permalink / raw)


Le samedi 27 janvier 2018 08:03:49 UTC+1, Randy Brukardt a écrit :
> ...
> >By the way, I have another question. There is no way to provide a default
> > instantiation to a formal package parameter?
> 
> Not in Ada 2012 or before. There is an open issue (it is one of those that 
> Emmanuel referenced in his message) to allow that. It hasn't progressed any 
> significant amount at this time.

Very interesting indeed, to have lawyers and implementers view on a language change proposal.

From my user point of view, the "or use" proposal looks very good.
It's simple (to write!), easy to read (much more in my opinion than "with Default_Type => ..." syntax).

I would just add that, when reading the comment on the ":=" proposal, that ":=" may seems to imply copying a type, I realized that I was already reading :
> procedure New_Line (Spacing : Positive_Count := 1);
as "give your own spacing, _or use_ 1 if none given", and not as 
"_copy_ 1 in Spacing if none given". 

So, IMHO, I wouldn't give a high weight to this argument.
 
And, actually, 
> procedure New_Line (Spacing : Positive_Count or use 1);
looks good too :-)
 

 

> (Aside: There are a LOT of ideas submitted for Ada 2020. Many good ideas are 
> likely to be left out simply because of lack of time and/or too much 
> change.)


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

* Re: Iterable container as generic parameter
  2018-01-27 11:38             ` Lionel Draghi
@ 2018-01-27 14:31               ` Jere
  0 siblings, 0 replies; 19+ messages in thread
From: Jere @ 2018-01-27 14:31 UTC (permalink / raw)


On Saturday, January 27, 2018 at 6:38:43 AM UTC-5, Lionel Draghi wrote:
> Le samedi 27 janvier 2018 08:03:49 UTC+1, Randy Brukardt a écrit :
> > ...
> > >By the way, I have another question. There is no way to provide a default
> > > instantiation to a formal package parameter?
> > 
> > Not in Ada 2012 or before. There is an open issue (it is one of those that 
> > Emmanuel referenced in his message) to allow that. It hasn't progressed any 
> > significant amount at this time.
> 
> Very interesting indeed, to have lawyers and implementers view on a language change proposal.
> 
> From my user point of view, the "or use" proposal looks very good.
> It's simple (to write!), easy to read (much more in my opinion than "with Default_Type => ..." syntax).

I agree.  I like the "or use" syntax best so far.

> 
> I would just add that, when reading the comment on the ":=" proposal, that ":=" may seems to imply copying a type, I realized that I was already reading :
> > procedure New_Line (Spacing : Positive_Count := 1);
> as "give your own spacing, _or use_ 1 if none given", and not as 
> "_copy_ 1 in Spacing if none given". 
> 
> So, IMHO, I wouldn't give a high weight to this argument.
>  
> And, actually, 
> > procedure New_Line (Spacing : Positive_Count or use 1);
> looks good too :-)
>  
While I don't like := as much as "or use", I will just add that
in today's Ada, := doesn't always imply copying.  It also can imply
build in place (somewhat similar to move semantics) in some cases.
So I agree that it isn't as much of a stretch.

I would still think "or use" is better though.

Another option that is less useful than default package types is
(making up a term here) package delegation/forwarding:

-- not legal Ada
with Specific_Package; use Specific_Package;

generic
   type Some_Type is limited private;
package Default_Package is new Base_Package
   (First_Param  => Specific_Thing,
    Second_Param => Some_Type);

I think you can do that or something similar in a generic formal,
but I don't think you can define a new generic like this.  It would
only be an alternative to default package formals (I would prefer
those), but would allow for defining a default package specification
for another.  It wouldn't be very useful if you wanted to default
a lot of things in different combinations though.


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

* Re: Iterable container as generic parameter
  2018-01-26  9:09       ` briot.emmanuel
  2018-01-26 22:32         ` Lionel Draghi
@ 2018-01-28 18:08         ` Lionel Draghi
  2018-01-29 13:34           ` briot.emmanuel
  1 sibling, 1 reply; 19+ messages in thread
From: Lionel Draghi @ 2018-01-28 18:08 UTC (permalink / raw)


Le 26/01/2018 à 10:09, emmanuel... a écrit :
>> But I probably would just use your original spec and add the container type
>> and iterator function, something like:
>>
>> generic
>>     type Cursor is (<>);
>>     with function Image (C : Cursor) return String;
>>     type Container (<>) is private;
>>     with package Iterator_Interfaces is
>>       new Ada.Iterator_Interfaces (Cursor, others => <>);
>>     with function Iterator (C : Container) return
>> Iterator_Interfaces.Forward_Iterator'Class;
>> function List_Image return String;
>>
> 
> I think that's a good starting point.

Ok, I have something that works (https://github.com/LionelDraghi/List_Image).

Instantiating this is not as simple as I hoped, but not that much a nightmare :

   with List_Image;

   with Ada.Containers.Indefinite_Hashed_Sets;
   with Ada.Strings.Hash_Case_Insensitive;
   ...
      -- Example here with a set of identifier
      package Id_Sets is new Ada.Containers.Indefinite_Hashed_Sets
        (String, Ada.Strings.Hash_Case_Insensitive, "=");
      Id_Set : Id_Sets.Set;

      use Id_Sets;
      function Id_Set_Image is new List_Image.Image
           (Cursor      => Cursor,
            Image       => Element,
            Iterator_If => Set_Iterator_Interfaces,
            Container   => Set,
            Iterator    => Iterate,
            Style       => List_Image.Bracketed_List_Style);
      ...
      Id_Set.Insert ("Salt");
      Id_Set.Insert ("Pepper");
      Put_Line (Id_Set_Image (Id_Set));


It becomes slightly more complex for Containers that don't directly export an Iterate function returning Forward_Iterator'class (but Reversible_Iterator'class).
You need then to provide a simple function :

   function Iterate (L : List) return
     List_Iterator_Interfaces.Forward_Iterator'Class is 
       (Iterate (L));

The signature Style package is generally simple, and may be application wide, shared among all List_Image instantiation.

Any idea to simplify is welcome.

-- 
-- Lionel


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

* Re: Iterable container as generic parameter
  2018-01-28 18:08         ` Lionel Draghi
@ 2018-01-29 13:34           ` briot.emmanuel
  2018-01-29 22:26             ` Lionel Draghi
  0 siblings, 1 reply; 19+ messages in thread
From: briot.emmanuel @ 2018-01-29 13:34 UTC (permalink / raw)


>       function Id_Set_Image is new List_Image.Image
>            (Cursor      => Cursor,
>             Image       => Element,
>             Iterator_If => Set_Iterator_Interfaces,
>             Container   => Set,
>             Iterator    => Iterate,
>             Style       => List_Image.Bracketed_List_Style);
> Any idea to simplify is welcome.

Seems to me that you need not pass Cursor explicitly here, since you are already
gettng it from Set_Iterator_Interfaces.

BTW, I would not use "Iterator_If" as the formal name. For me, this would be a signature
package that wraps iterator, but might skip elements that do not match a predicate (a way to display every other element in a list, for instance, or elements up to a certain point only,...) A whole other set of signature packages in there :-)


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

* Re: Iterable container as generic parameter
  2018-01-29 13:34           ` briot.emmanuel
@ 2018-01-29 22:26             ` Lionel Draghi
  2018-01-29 23:00               ` Randy Brukardt
  2018-01-30 15:13               ` Shark8
  0 siblings, 2 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-29 22:26 UTC (permalink / raw)


Le lundi 29 janvier 2018 14:34:07 UTC+1, briot.e...@gmail.com a écrit :
> >       function Id_Set_Image is new List_Image.Image
> >            (Cursor      => Cursor,
> >             Image       => Element,
> >             Iterator_If => Set_Iterator_Interfaces,
> >             Container   => Set,
> >             Iterator    => Iterate,
> >             Style       => List_Image.Bracketed_List_Style);
> > Any idea to simplify is welcome.
> 
> Seems to me that you need not pass Cursor explicitly here, since you are already
> gettng it from Set_Iterator_Interfaces.

Good point indeed.

This compile fine :

with Ada.Iterator_Interfaces;

package List_Image is

   generic
      with package Iterator_If is new Ada.Iterator_Interfaces (<>);
      use Iterator_If;
     
      with function Image (C : Cursor) return String is <>;
  
   function Image return String;

end List_Image;

But this :

package body List_Image is

   function Image return String is
      C1 : Cursor;
   begin
      return "";
   end Image;

end List_Image;

cause a :
        4:12 invalid use of type before its full declaration
        4:7 premature usage of incomplete type "Ada.Iterator_Interfaces.Cursor" from instance at list_image.ads:6

Am I missing something?

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

* Re: Iterable container as generic parameter
  2018-01-29 22:26             ` Lionel Draghi
@ 2018-01-29 23:00               ` Randy Brukardt
  2018-01-30 22:35                 ` Lionel Draghi
  2018-01-30 15:13               ` Shark8
  1 sibling, 1 reply; 19+ messages in thread
From: Randy Brukardt @ 2018-01-29 23:00 UTC (permalink / raw)


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

The Cursor type you are getting from the formal interface package is an 
incomplete type. You can't do much with an incomplete type.

Now, I'd have to read the RM for hours to figure out for sure whether you 
are supposed to get the formal or the actual type in this case. It wouldn't 
surprise me if it is supposed to be the formal type, in which case, your 
original version was better. Otherwise, it could be a GNAT bug, but, again, 
I'm not sure. Practically, I'd assume that it is the formal and use your 
original formulation (which clearly doesn't have a problem).

                                            Randy.


"Lionel Draghi" <lionel.draghi@gmail.com> wrote in message 
news:d5ea6fa8-13db-4043-b0ab-6deac9e61b7e@googlegroups.com...
Le lundi 29 janvier 2018 14:34:07 UTC+1, briot.e...@gmail.com a écrit :
> >       function Id_Set_Image is new List_Image.Image
> >            (Cursor      => Cursor,
> >             Image       => Element,
> >             Iterator_If => Set_Iterator_Interfaces,
> >             Container   => Set,
> >             Iterator    => Iterate,
> >             Style       => List_Image.Bracketed_List_Style);
> > Any idea to simplify is welcome.
>
> Seems to me that you need not pass Cursor explicitly here, since you are 
> already
> gettng it from Set_Iterator_Interfaces.

Good point indeed.

This compile fine :

with Ada.Iterator_Interfaces;

package List_Image is

   generic
      with package Iterator_If is new Ada.Iterator_Interfaces (<>);
      use Iterator_If;

      with function Image (C : Cursor) return String is <>;

   function Image return String;

end List_Image;

But this :

package body List_Image is

   function Image return String is
      C1 : Cursor;
   begin
      return "";
   end Image;

end List_Image;

cause a :
        4:12 invalid use of type before its full declaration
        4:7 premature usage of incomplete type 
"Ada.Iterator_Interfaces.Cursor" from instance at list_image.ads:6

Am I missing something? 



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

* Re: Iterable container as generic parameter
  2018-01-29 22:26             ` Lionel Draghi
  2018-01-29 23:00               ` Randy Brukardt
@ 2018-01-30 15:13               ` Shark8
  1 sibling, 0 replies; 19+ messages in thread
From: Shark8 @ 2018-01-30 15:13 UTC (permalink / raw)


On Monday, January 29, 2018 at 3:26:44 PM UTC-7, Lionel Draghi wrote:
> package List_Image is
> 
>    generic
>       with package Iterator_If is new Ada.Iterator_Interfaces (<>);
>       use Iterator_If;
>      
>       with function Image (C : Cursor) return String is <>;
>   
>    function Image return String;
> 
> end List_Image;

Interesting; I didn't know a use-clause was allowed in the generic parameters.
(I just use full qualification: "Iterator_If.Cusror".)


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

* Re: Iterable container as generic parameter
  2018-01-29 23:00               ` Randy Brukardt
@ 2018-01-30 22:35                 ` Lionel Draghi
  2018-01-30 23:32                   ` Lionel Draghi
  2018-01-31  0:15                   ` Lionel Draghi
  0 siblings, 2 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-30 22:35 UTC (permalink / raw)


Le mardi 30 janvier 2018 00:00:20 UTC+1, Randy Brukardt a écrit :
> The Cursor type you are getting from the formal interface package is an 
> incomplete type. You can't do much with an incomplete type.
> 
> Now, I'd have to read the RM for hours to figure out for sure whether you 
> are supposed to get the formal or the actual type in this case. It wouldn't 
> surprise me if it is supposed to be the formal type, in which case, your 
> original version was better. Otherwise, it could be a GNAT bug, but, again, 
> I'm not sure. Practically, I'd assume that it is the formal and use your 
> original formulation (which clearly doesn't have a problem).
 
Actually, the second Emmanuel's point about making a signature package of  Iterator related stuff was the solution to this problem also, because the Cursor is no more used where it is instantiated.

I probably won't finish it tonight, but its becoming nice and easy to instantiate!
(I'll be back with a v0.2.0 before the FOSDEM!)



 

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

* Re: Iterable container as generic parameter
  2018-01-30 22:35                 ` Lionel Draghi
@ 2018-01-30 23:32                   ` Lionel Draghi
  2018-01-31  0:15                   ` Lionel Draghi
  1 sibling, 0 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-30 23:32 UTC (permalink / raw)


As an overview :

   -- -------------------------------------------------------------------------
   --                             Cursors
   -- -------------------------------------------------------------------------
   generic
      type Container (<>) is limited private;
      type Cursor is private;
      with function First (Self : Container) return Cursor is <>;
      with function Has_Element (Pos : Cursor) return Boolean is <>;
      with function Next        (Pos : Cursor) return Cursor  is <>;
   package Cursors_Signature is end;

   -- -------------------------------------------------------------------------
   --                       The Image function
   -- -------------------------------------------------------------------------
   generic
      with package Cursors is new Cursors_Signature (<>);
      with function Image (C : Cursors.Cursor) return String is <>;
      with package Style is new List_Style (<>);
   function Image (Cont : in Cursors.Container) return String;

Image's formals reflect the three parameters of the function, no garbage, that's not to bad.

And instantiation is pretty easy :

      use Integer_Lists;
      package Integer_Lists_Cursors is new List_Image.Cursors_Signature 
        (Container => List,
         Cursor    => Cursor);
      
      function Image (C : Cursor) return String is
           (Integer'Image (Element (C)));

      function Integer_List_Image is new List_Image.Image
        (Cursors => Integer_Lists_Cursors,
         Style   => List_Image.Bracketed_List_Style);


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

* Re: Iterable container as generic parameter
  2018-01-30 22:35                 ` Lionel Draghi
  2018-01-30 23:32                   ` Lionel Draghi
@ 2018-01-31  0:15                   ` Lionel Draghi
  1 sibling, 0 replies; 19+ messages in thread
From: Lionel Draghi @ 2018-01-31  0:15 UTC (permalink / raw)


Emmanuel gave the answer here: 
https://stackoverflow.com/questions/33496741/rules-for-formal-incomplete-types-in-ada-2012


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

end of thread, other threads:[~2018-01-31  0:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-25  0:22 Iterable container as generic parameter Lionel Draghi
2018-01-25  3:36 ` Randy Brukardt
2018-01-25 14:58   ` Lionel Draghi
2018-01-25 18:26     ` briot.emmanuel
2018-01-26  4:50     ` Randy Brukardt
2018-01-26  9:09       ` briot.emmanuel
2018-01-26 22:32         ` Lionel Draghi
2018-01-27  7:03           ` Randy Brukardt
2018-01-27 11:38             ` Lionel Draghi
2018-01-27 14:31               ` Jere
2018-01-28 18:08         ` Lionel Draghi
2018-01-29 13:34           ` briot.emmanuel
2018-01-29 22:26             ` Lionel Draghi
2018-01-29 23:00               ` Randy Brukardt
2018-01-30 22:35                 ` Lionel Draghi
2018-01-30 23:32                   ` Lionel Draghi
2018-01-31  0:15                   ` Lionel Draghi
2018-01-30 15:13               ` Shark8
2018-01-26 23:07 ` Lionel Draghi

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