* 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-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 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
* 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-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
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