* A few questions @ 2015-10-31 20:29 Laurent 2015-10-31 20:49 ` Dmitry A. Kazakov ` (6 more replies) 0 siblings, 7 replies; 73+ messages in thread From: Laurent @ 2015-10-31 20:29 UTC (permalink / raw) Hi I need a range of Dates. So I tried this: Begin_Date: Dates.Object; End_Date: Dates.Object; -- Dates is a package from an earlier example in my Ada95 book. It is based on Ada.Calendars. I prefer to use -- Dates because I actually need only the date, I don't care/ need the hour. I also find the name "Time" for -- something like "2015/10/31 21:00:00" confusing but that's just my opinion. That doesn't work unfortunately and the compiler is right to complain: subtype Period is range Begin_Date .. End_Date; I naively thought that it could be so easy. I could solve this problem with a few loops and filling an array or a list with the generated dates but the loop thing will be probably very ugly/complicated. For the array I also have to know how many dates I actually have between Begin_Date and End_Date. I have tried to I have found in Ada.Calendar a: function "-" (L,R:Time) return Duration Is it possible to make a casting to convert my Date type in (Ada.Calendar) Time type: Today : Ada.Calendar.Time:= Time(Date); -- or something like that. I could of course use the Getters from Dates and then construct a new Time. More of curiosity than an actual problem. Well of course I could simply use Ada.Calendar. So is there an existing package which generates a range of Dates from .. to ? Feels like cheating but causes less frustration. Thanks Laurent PS: need this range of dates because the log files I want to read and extract informations from are all named like this: vba-yyyymmdd.log where obviously yyyymmdd is the date. The program generates a new file every date an stores the communication it treated in it. I want to read this files and extract the messages which passed. Is more an exercise than actually a need to do it. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent @ 2015-10-31 20:49 ` Dmitry A. Kazakov 2015-11-01 13:16 ` Laurent 2015-11-01 0:25 ` Jeffrey R. Carter ` (5 subsequent siblings) 6 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-10-31 20:49 UTC (permalink / raw) On Sat, 31 Oct 2015 13:29:51 -0700 (PDT), Laurent wrote: > I need a range of Dates. > > So I tried this: > > Begin_Date: Dates.Object; > End_Date: Dates.Object; > -- Dates is a package from an earlier example in my Ada95 book. It is based on Ada.Calendars. I prefer to use > -- Dates because I actually need only the date, I don't care/ need the hour. I also find the name "Time" for > -- something like "2015/10/31 21:00:00" confusing but that's just my opinion. > > That doesn't work unfortunately and the compiler is right to complain: > > subtype Period is range Begin_Date .. End_Date; 1. How is this subtype would be different from Date? 2. Date is not a numeric type to have ranges 3. Date cannot be a numeric type because arithmetic operations would not make sense: D1 + D2 is what? > I naively thought that it could be so easy. Yes, because it is wrong. > I have found in Ada.Calendar a: function "-" (L,R:Time) return Duration Similarly D1 - D2 is a Duration, not a date. Likewise you can add duration to a date, but not a date to date. > Is it possible to make a casting to convert my Date type in (Ada.Calendar) Time type: > > Today : Ada.Calendar.Time:= Time(Date); -- or something like that. No problem. You would have an equivalent of Year, Month, Day functions defined for Date. Then you would call Time_Of. That is. > So is there an existing package which generates a range of Dates from .. to? No, but you could have an abstract iterator for dates in Ada 2012. > PS: need this range of dates because the log files I want to read and > extract informations from are all named like this: vba-yyyymmdd.log where > obviously yyyymmdd is the date. The program generates a new file every > date an stores the communication it treated in it. See Ada.Calendar.Formatting.Image. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:49 ` Dmitry A. Kazakov @ 2015-11-01 13:16 ` Laurent 0 siblings, 0 replies; 73+ messages in thread From: Laurent @ 2015-11-01 13:16 UTC (permalink / raw) On Saturday, 31 October 2015 21:49:24 UTC+1, Dmitry A. Kazakov wrote: > > subtype Period is range Begin_Date .. End_Date; > > 1. How is this subtype would be different from Date? > Perhaps in some declarative language where lists are an fundamental part of the language itself the compiler could be smart enough to make Period a list and fill it with dates from..to? Yeah I know mind-reading compiler and World of Fantasycraft :) > 2. Date is not a numeric type to have ranges Agreed > 3. Date cannot be a numeric type because arithmetic operations would not > make sense: D1 + D2 is what? Nonsense :) > > I naively thought that it could be so easy. > > Yes, because it is wrong. What? Being naive or thinking that it could/should be easy? :) > > I have found in Ada.Calendar a: function "-" (L,R:Time) return Duration > > Similarly D1 - D2 is a Duration, not a date. Likewise you can add duration > to a date, but not a date to date. > > > Is it possible to make a casting to convert my Date type in (Ada.Calendar) Time type: > > > > Today : Ada.Calendar.Time:= Time(Date); -- or something like that. > > No problem. You would have an equivalent of Year, Month, Day functions > defined for Date. Then you would call Time_Of. That is. I actually mentioned the "-" only because it would spare me from having to roll my own to figure out how many days are between D1 and D2. But I think that it is probably not necessary at all. > > So is there an existing package which generates a range of Dates from .. to? > > No, but you could have an abstract iterator for dates in Ada 2012. > > > PS: need this range of dates because the log files I want to read and > > extract informations from are all named like this: vba-yyyymmdd.log where > > obviously yyyymmdd is the date. The program generates a new file every > > date an stores the communication it treated in it. > > See Ada.Calendar.Formatting.Image. I think getting the names done is the easiest part. When first took a look at the log files I thought that it would be difficult to extract the informations I am looking for. But no getting some continuous dates from .. to is the real PITA. Otherwise it would be boring. Thanks ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent 2015-10-31 20:49 ` Dmitry A. Kazakov @ 2015-11-01 0:25 ` Jeffrey R. Carter 2015-11-01 13:30 ` Laurent 2015-11-03 6:25 ` Randy Brukardt 2015-11-01 9:05 ` Jacob Sparre Andersen ` (4 subsequent siblings) 6 siblings, 2 replies; 73+ messages in thread From: Jeffrey R. Carter @ 2015-11-01 0:25 UTC (permalink / raw) On 10/31/2015 01:29 PM, Laurent wrote: > > I need a range of Dates. > > So is there an existing package which generates a range of Dates from .. to > ? > > PS: need this range of dates because the log files I want to read and extract > informations from are all named like this: vba-yyyymmdd.log where obviously > yyyymmdd is the date. The program generates a new file every date an stores > the communication it treated in it. > > I want to read this files and extract the messages which passed. Is more an > exercise than actually a need to do it. I'm not aware of any such pkg. On the other hand, I'm not sure you need it. Do you really need to store all the dates in the range? You could process the file for date D, then the file for date D + 1, ..., until you have processed all the desired files. Conceptually the idea of an operation function "+" (Left : in Dates.Object; Right : in Integer) return Dates.Object; makes sense; without knowing the details of the implementation of Dates.Object I have no idea how easy it would be. For Ada.Calendar.Time, one would simply add Right * Ada.Calendar.Day_Duration'Last. -- Jeff Carter "Monsieur Arthur King, who has the brain of a duck, you know." Monty Python & the Holy Grail 09 ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 0:25 ` Jeffrey R. Carter @ 2015-11-01 13:30 ` Laurent 2015-11-03 6:25 ` Randy Brukardt 1 sibling, 0 replies; 73+ messages in thread From: Laurent @ 2015-11-01 13:30 UTC (permalink / raw) On Sunday, 1 November 2015 01:25:22 UTC+1, Jeffrey R. Carter wrote: > I'm not aware of any such pkg. On the other hand, I'm not sure you need it. Do > you really need to store all the dates in the range? You could process the file > for date D, then the file for date D + 1, ..., until you have processed all the > desired files. I don't think that I need to store them. It would allow me to use a simple loop later on and hide the ugly things somewhere else. > Conceptually the idea of an operation > > function "+" (Left : in Dates.Object; Right : in Integer) return Dates.Object; > > makes sense; without knowing the details of the implementation of Dates.Object I > have no idea how easy it would be. For Ada.Calendar.Time, one would simply add > Right * Ada.Calendar.Day_Duration'Last. Sounds like a good idea. I am actually reinventing the wheel because most of the functionality already is in the Calendar package. I tried to understand how this package works but there are few intermediate steps which I don't get. IE: Time_Rep? And there are others. They are probably required for managing one special problem which happens once a century. At least I will perhaps learn why the package has been designed like this. Thanks ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 0:25 ` Jeffrey R. Carter 2015-11-01 13:30 ` Laurent @ 2015-11-03 6:25 ` Randy Brukardt 1 sibling, 0 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-03 6:25 UTC (permalink / raw) "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message news:n13m1a$p3c$1@dont-email.me... > On 10/31/2015 01:29 PM, Laurent wrote: >> >> I need a range of Dates. >> >> So is there an existing package which generates a range of Dates from .. >> to >> ? >> >> PS: need this range of dates because the log files I want to read and >> extract >> informations from are all named like this: vba-yyyymmdd.log where >> obviously >> yyyymmdd is the date. The program generates a new file every date an >> stores >> the communication it treated in it. >> >> I want to read this files and extract the messages which passed. Is more >> an >> exercise than actually a need to do it. > > I'm not aware of any such pkg. On the other hand, I'm not sure you need > it. Do > you really need to store all the dates in the range? You could process the > file > for date D, then the file for date D + 1, ..., until you have processed > all the > desired files. > > Conceptually the idea of an operation > > function "+" (Left : in Dates.Object; Right : in Integer) return > Dates.Object; > > makes sense; without knowing the details of the implementation of > Dates.Object I > have no idea how easy it would be. For Ada.Calendar.Time, one would simply > add > Right * Ada.Calendar.Day_Duration'Last. Or easier still, just use Ada.Calendar.Arithmetic, which has operations for adding numbers of days to a Ada.Calendar.Time (added in Ada 2005). (This is hard to do in Ada 95 if you need to add more than one day at a time.) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent 2015-10-31 20:49 ` Dmitry A. Kazakov 2015-11-01 0:25 ` Jeffrey R. Carter @ 2015-11-01 9:05 ` Jacob Sparre Andersen 2015-11-01 13:40 ` Laurent 2015-11-01 13:42 ` brbarkstrom ` (3 subsequent siblings) 6 siblings, 1 reply; 73+ messages in thread From: Jacob Sparre Andersen @ 2015-11-01 9:05 UTC (permalink / raw) Laurent <lutgenl@icloud.com> writes: > I need a range of Dates. As a type? subtype Period is Date with Dynamic_Predicate => Begin_Date <= Period and Period <= End_Date; As an object? type Dates is array (Positive range <>) of Date; Period : constant Dates := (Begin_Date, Begin_Date + 1 * Days, Begin_Date + 2 * Days, ... End_Date); As an iterator? -- Too much work to write here. :-) Greetings, Jacob -- "The pictures on radio are always so much better than those on TV." -- Pratchet, Stewart & Cohen ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 9:05 ` Jacob Sparre Andersen @ 2015-11-01 13:40 ` Laurent 2015-11-01 18:14 ` Jacob Sparre Andersen 0 siblings, 1 reply; 73+ messages in thread From: Laurent @ 2015-11-01 13:40 UTC (permalink / raw) On Sunday, 1 November 2015 10:05:17 UTC+1, Jacob Sparre Andersen wrote: > As a type? > > subtype Period is Date > with Dynamic_Predicate => Begin_Date <= Period and Period <= End_Date; And that would allow me to use it like this: for I in Period'Range loop... Feels to much like magic that it could actually work :) > As an object? > > type Dates is array (Positive range <>) of Date; > Period : constant Dates := (Begin_Date, > Begin_Date + 1 * Days, > Begin_Date + 2 * Days, > ... > End_Date); > > As an iterator? Don't think that is necessary. Could still try to feed it to my self rolled linked list package to find out if it is able to store the dates. Thanks ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 13:40 ` Laurent @ 2015-11-01 18:14 ` Jacob Sparre Andersen 2015-11-01 18:40 ` Laurent 0 siblings, 1 reply; 73+ messages in thread From: Jacob Sparre Andersen @ 2015-11-01 18:14 UTC (permalink / raw) Laurent <lutgenl@icloud.com> writes: >> subtype Period is Date >> with Dynamic_Predicate => Begin_Date <= Period and Period <= End_Date; > > And that would allow me to use it like this: > > for I in Period'Range loop... No. That wasn't what you asked for. >> As an iterator? > > Don't think that is necessary. Could still try to feed it to my self > rolled linked list package to find out if it is able to store the > dates. Why worry about storing the dates, if you just want to iterate over a range? Greetings, Jacob -- "Lots of information, strong cast, but a bit weak on the narrative." -- Pratchet, Stewart & Cohen reviews a phone directory ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 18:14 ` Jacob Sparre Andersen @ 2015-11-01 18:40 ` Laurent 0 siblings, 0 replies; 73+ messages in thread From: Laurent @ 2015-11-01 18:40 UTC (permalink / raw) On Sunday, 1 November 2015 19:14:09 UTC+1, Jacob Sparre Andersen wrote: > >> subtype Period is Date > >> with Dynamic_Predicate => Begin_Date <= Period and Period <= End_Date; > > > > And that would allow me to use it like this: > > > > for I in Period'Range loop... > > No. That wasn't what you asked for. No didn't ask in the beginning but it was my intention since the begin to use it like that. Sorry my error of not mentioning it immediately. > Why worry about storing the dates, if you just want to iterate over a > range? Curiosity ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent ` (2 preceding siblings ...) 2015-11-01 9:05 ` Jacob Sparre Andersen @ 2015-11-01 13:42 ` brbarkstrom 2015-11-01 13:52 ` Laurent 2015-11-01 15:15 ` Dennis Lee Bieber 2015-11-01 16:33 ` gautier_niouzes ` (2 subsequent siblings) 6 siblings, 2 replies; 73+ messages in thread From: brbarkstrom @ 2015-11-01 13:42 UTC (permalink / raw) You could translate the YYYYMMDD time into a continuous numerical value and then use Ada.Real_Time to convert that value to time in seconds from some selected starting point. The way astronomers track time is to go over to counting seconds from Jan. 0, 2013 BCE. The variable is called Astronomical Julian Date. The current value is fairly large, particularly if you want a time resolution in microseconds. GPS time is close to Julian Date, but uses a starting date closer to the present. Seidelmann, P. K., 2006: Explanatory Supplement to the Astronomical Almanac, University Science Books, Sausalito, CA is the definitive reference. Savage, N., 2015: Split Second, Comm. ACM, 58, No. 9, 12-14 deals with "The issue of whether to add a `leap second' to square the clock with the Earth's orbit pits time specialists against IT." (quoting from the index to that issue of CACM). To put it simply, Astronomical Julian Date (and relatives) produces a uniform time record in seconds, It also makes sure that all dates/times are reduced to the same time zone at the Greenwich meridian. The usual IT convention (YYYYMMDD) is non-uniform (for example, Feb. may have 28 or 29 days - while Jul. always has 31). It would seem that if your application might move to a geographically distributed environment, the Julian Date would be sensible. On the other hand, Julian Date is not readily interpretable to humans. Bruce B. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 13:42 ` brbarkstrom @ 2015-11-01 13:52 ` Laurent 2015-11-01 17:59 ` Jeffrey R. Carter 2015-11-02 13:25 ` brbarkstrom 2015-11-01 15:15 ` Dennis Lee Bieber 1 sibling, 2 replies; 73+ messages in thread From: Laurent @ 2015-11-01 13:52 UTC (permalink / raw) On Sunday, 1 November 2015 14:42:17 UTC+1, brbar...@gmail.com wrote: > You could translate the YYYYMMDD time into a continuous numerical value > and then use Ada.Real_Time to convert that value to time in seconds from > some selected starting point. > > The way astronomers track time is to go over to counting seconds from > Jan. 0, 2013 BCE. The variable is called Astronomical Julian Date. > The current value is fairly large, particularly if you want a time > resolution in microseconds. GPS time is close to Julian Date, but > uses a starting date closer to the present. > > Seidelmann, P. K., 2006: Explanatory Supplement to the Astronomical > Almanac, University Science Books, Sausalito, CA > > is the definitive reference. > > Savage, N., 2015: Split Second, Comm. ACM, 58, No. 9, 12-14 > > deals with "The issue of whether to add a `leap second' to square > the clock with the Earth's orbit pits time specialists against IT." > (quoting from the index to that issue of CACM). > > To put it simply, Astronomical Julian Date (and relatives) produces > a uniform time record in seconds, It also makes sure that all dates/times > are reduced to the same time zone at the Greenwich meridian. The usual > IT convention (YYYYMMDD) is non-uniform (for example, Feb. may have 28 > or 29 days - while Jul. always has 31). It would seem that if your > application might move to a geographically distributed environment, > the Julian Date would be sensible. On the other hand, Julian Date is > not readily interpretable to humans. > > Bruce B. Thanks for the info but I fear that it is more than overkill. It also shows that most "standards" have gotten this status only because things have been like that before and not because they are the best possible solution. So if you have a better solution than the actual one but are not part of a large community which supports this, then you can burn it immediately. Only because no one wants to change a thing and prefer to use some crappy solution over changing something and investing time and effort. Somehow this world sucks. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 13:52 ` Laurent @ 2015-11-01 17:59 ` Jeffrey R. Carter 2015-11-01 18:35 ` Laurent 2015-11-02 13:25 ` brbarkstrom 1 sibling, 1 reply; 73+ messages in thread From: Jeffrey R. Carter @ 2015-11-01 17:59 UTC (permalink / raw) On 11/01/2015 06:52 AM, Laurent wrote: > > So if you have a better solution than the actual one but are not part of a > large community which supports this, then you can burn it immediately. Only > because no one wants to change a thing and prefer to use some crappy solution > over changing something and investing time and effort. Sure. Thirty years ago I worked on a research project funded by a black project. The researcher said at the beginning that the project wouldn't use our results, no matter how good they were, because the project wasn't in trouble. The standard approach to the problem was quite complex and very calculation intensive. The researcher's approach worked, was more accurate than the theoretical minimum for the standard approach, and required fewer calculations. The project stuck with the standard approach. > Somehow this world sucks. Then you die. -- Jeff Carter "It's symbolic of his struggle against reality." Monty Python's Life of Brian 78 ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 17:59 ` Jeffrey R. Carter @ 2015-11-01 18:35 ` Laurent 0 siblings, 0 replies; 73+ messages in thread From: Laurent @ 2015-11-01 18:35 UTC (permalink / raw) On Sunday, 1 November 2015 18:59:47 UTC+1, Jeffrey R. Carter wrote: > > Somehow this world sucks. > > Then you die. True for everybody independently of the fact that the world sucks. Which only has an influence on the when and how :) But that belongs into some other google group ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 13:52 ` Laurent 2015-11-01 17:59 ` Jeffrey R. Carter @ 2015-11-02 13:25 ` brbarkstrom 1 sibling, 0 replies; 73+ messages in thread From: brbarkstrom @ 2015-11-02 13:25 UTC (permalink / raw) > Thanks for the info but I fear that it is more than overkill. > > It also shows that most "standards" have gotten this status only because things have been like that before and not because they are the best possible solution. > > So if you have a better solution than the actual one but are not part of a large community which supports this, then you can burn it immediately. Only because no one wants to change a thing and prefer to use some crappy solution over changing something and investing time and effort. > > Somehow this world sucks. That's a bit oversimplified. "Standards" get adopted because some group reaches a consensus. In the case of botany, getting to agreement on the standard Linnean nomenclature required about a century (roughly 1800-1900) and five or six international congresses. In the IT world, UDDI was of interest to a number of large businesses - and then they dropped the effort because it didn't seem to be in their interest to continue. Note also that there may not be an agreement on what is the "best" solution. That's particularly the case with time standards. A classical astronomer would probably prefer a time standard that kept the Sun in the same place for a given day of the year - and would put up with leap seconds on an occasional basis. A physicist would prefer that time marches uniformly, like atomic clocks. An IT specialist may prefer using civil time because it's understandable - but suffers from complicated representations and irregularities, as well as the possibility that someone forgot to put in a standard time zone. Bruce B. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 13:42 ` brbarkstrom 2015-11-01 13:52 ` Laurent @ 2015-11-01 15:15 ` Dennis Lee Bieber 1 sibling, 0 replies; 73+ messages in thread From: Dennis Lee Bieber @ 2015-11-01 15:15 UTC (permalink / raw) On Sun, 1 Nov 2015 05:42:16 -0800 (PST), brbarkstrom@gmail.com declaimed the following: >To put it simply, Astronomical Julian Date (and relatives) produces >a uniform time record in seconds, It also makes sure that all dates/times >are reduced to the same time zone at the Greenwich meridian. The usual >IT convention (YYYYMMDD) is non-uniform (for example, Feb. may have 28 >or 29 days - while Jul. always has 31). It would seem that if your >application might move to a geographically distributed environment, >the Julian Date would be sensible. On the other hand, Julian Date is >not readily interpretable to humans. > There's also the minor touch that the "day" rolls over at noon, not midnight. After all, when one's work runs the dark hours, who wants to fiddle with a day change in the middle of one's observations. If the dates don't need to go back too far (Nov 17 1858, Modified Julian Date is usable, and puts the day change back to midnight. As I recall MJD was the reference point used by the VMS operating system. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent ` (3 preceding siblings ...) 2015-11-01 13:42 ` brbarkstrom @ 2015-11-01 16:33 ` gautier_niouzes 2015-11-01 16:36 ` gautier_niouzes 2015-11-01 18:17 ` Stephen Leake 2015-11-02 17:45 ` Simon Wright 6 siblings, 1 reply; 73+ messages in thread From: gautier_niouzes @ 2015-11-01 16:33 UTC (permalink / raw) What about something like this: Begin_Date: Time:= ...; End_Date: Time:= ...; Day_Seconds: constant Duration:= 86400.0; Days: constant Natural:= Natural(End_Date-Begin_Date) / Day_Seconds; subtype Period is Natural range 0..Days; ? As a bonus, you have below a display function from my toolbox :-) . _________________________ Gautier's Ada programming http://gautiersblog.blogspot.com/search/label/Ada NB: follow the above link for a valid e-mail address -- Time_display returns date & time, current or given. -- E.g.: "2013/08/01 05:49:51" -- Useful for a log file or a display of a lengthy operation. -- This is Ada 83 compatible. Format accepted by SQL queries. -- -- 32- or 64-bit: DEC/Compaq/HP Ada (83), GNAT (95/2005), ObjectAda (95) -- 16-bit: Meridian (83) -> Long_Integer is 32-bit -- 16-bit: Janus 2.x (83): KO: no Long_Integer -- -- Test program in following comment: -- -- with Text_IO,Time_display;procedure Test is begin Text_IO.Put(Time_display);end; with Calendar; function Time_display( T : Calendar.Time:= Calendar.Clock; Seconds : Boolean := True; Intra_day: Boolean := True ) return String is use Calendar; subtype Sec_int is Long_Integer; -- must contain 86_400 s : constant Sec_int:= Sec_int( Calendar.Seconds(T) ); m : constant Sec_int:= s / 60; -- + 100: trick for obtaining 0x sY : constant String:= Integer'Image( Year(T)); sM : constant String:= Integer'Image( Month(T) + 100); sD : constant String:= Integer'Image( Day(T) + 100); shr: constant String:= Sec_int'Image( m / 60 + 100); smn: constant String:= Sec_int'Image( m mod 60 + 100); ssc: constant String:= Sec_int'Image( s mod 60 + 100); -- function Optional_seconds return String is begin if Seconds then return ':' & ssc( ssc'Last-1 .. ssc'Last ); else return ""; end if; end Optional_seconds; -- function Optional_intra_day return String is begin if Intra_day then return " " & shr( shr'Last-1 .. shr'Last ) & ':' & smn( smn'Last-1 .. smn'Last ) & Optional_seconds; else return ""; end if; end Optional_intra_day; begin return sY( sY'Last-3 .. sY'Last ) & '/' & -- not Year 10'000 compliant. sM( sM'Last-1 .. sM'Last ) & '/' & sD( sD'Last-1 .. sD'Last ) & Optional_intra_day; end Time_display; ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 16:33 ` gautier_niouzes @ 2015-11-01 16:36 ` gautier_niouzes 0 siblings, 0 replies; 73+ messages in thread From: gautier_niouzes @ 2015-11-01 16:36 UTC (permalink / raw) > Days: constant Natural:= Natural(End_Date-Begin_Date) / Day_Seconds; Probably better so :-) : Natural((End_Date-Begin_Date) / Day_Seconds); _________________________ Gautier's Ada programming http://sf.net/users/gdemont ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent ` (4 preceding siblings ...) 2015-11-01 16:33 ` gautier_niouzes @ 2015-11-01 18:17 ` Stephen Leake 2015-11-01 18:53 ` Laurent 2015-11-02 17:45 ` Simon Wright 6 siblings, 1 reply; 73+ messages in thread From: Stephen Leake @ 2015-11-01 18:17 UTC (permalink / raw) Laurent <lutgenl@icloud.com> writes: > Hi > > I need a range of Dates. Why? What will that do for you that your current Date package will not do? Until we know that, it's hard to say what code you should implement. > Begin_Date: Dates.Object; > End_Date: Dates.Object; Why isn't this enough for your needs? > subtype Period is range Begin_Date .. End_Date; What operations to do want to have for this type? -- -- Stephe ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 18:17 ` Stephen Leake @ 2015-11-01 18:53 ` Laurent 2015-11-02 0:41 ` Dennis Lee Bieber 2015-11-02 16:42 ` Stephen Leake 0 siblings, 2 replies; 73+ messages in thread From: Laurent @ 2015-11-01 18:53 UTC (permalink / raw) On Sunday, 1 November 2015 19:17:44 UTC+1, Stephen Leake wrote: > > I need a range of Dates. > > Why? > > What will that do for you that your current Date package will not do? > > Until we know that, it's hard to say what code you should implement. > > > Begin_Date: Dates.Object; > > End_Date: Dates.Object; > > Why isn't this enough for your needs? No because my package had nothing else than set/get the different components of Date and a constructor. and an IO package for formatting I have now added "+" (L: Date, R : Positive) return Date which should work the way I think it should. Perhaps . First need to test if the result is correct. Another day. > > subtype Period is range Begin_Date .. End_Date; > > What operations to do want to have for this type? Hm none. Just would need the possibility to use it in a loop for the 'Range. But hey I am a noob so I quite often asks silly questions :) ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 18:53 ` Laurent @ 2015-11-02 0:41 ` Dennis Lee Bieber 2015-11-02 16:42 ` Stephen Leake 1 sibling, 0 replies; 73+ messages in thread From: Dennis Lee Bieber @ 2015-11-02 0:41 UTC (permalink / raw) On Sun, 1 Nov 2015 10:53:31 -0800 (PST), Laurent <lutgenl@icloud.com> declaimed the following: > >Hm none. Just would need the possibility to use it in a loop for the 'Range. But hey I am a noob so I quite often asks silly questions :) And the simplest is probably to have some procedure/function that converts between a calendar (day month year) and some cardinal/integer referenced to some epoch date. So your range becomes a range of cardinal values. Which puts us back to JD, MJD (you probably don't want JD since xxxx.0 is NOON, and midnight is xxxx.5), C/UNIX seconds since some epoch based on some date in 1970, etc. -- Wulfraed Dennis Lee Bieber AF6VN wlfraed@ix.netcom.com HTTP://wlfraed.home.netcom.com/ ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-01 18:53 ` Laurent 2015-11-02 0:41 ` Dennis Lee Bieber @ 2015-11-02 16:42 ` Stephen Leake 1 sibling, 0 replies; 73+ messages in thread From: Stephen Leake @ 2015-11-02 16:42 UTC (permalink / raw) Laurent <lutgenl@icloud.com> writes: > On Sunday, 1 November 2015 19:17:44 UTC+1, Stephen Leake wrote: > >> > subtype Period is range Begin_Date .. End_Date; >> >> What operations to do want to have for this type? > > Hm none. Just would need the possibility to use it in a loop for the > 'Range. I'm guessing you want the loop to cover each day in the date range? In that case, Julian Days (or days since some other epoch) will allow this in a "for" loop. Or you can write a function: function Next_Day (I : in Date) return Date; and use that in an "exit" loop. -- -- Stephe ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-10-31 20:29 A few questions Laurent ` (5 preceding siblings ...) 2015-11-01 18:17 ` Stephen Leake @ 2015-11-02 17:45 ` Simon Wright 2015-11-02 18:48 ` Simon Wright 2015-11-03 6:40 ` Randy Brukardt 6 siblings, 2 replies; 73+ messages in thread From: Simon Wright @ 2015-11-02 17:45 UTC (permalink / raw) Laurent <lutgenl@icloud.com> writes: > Hi > > I need a range of Dates. I wrote the attached, using generalized iteration, which bears a strong resemblance to the standard container iteration (the names bear too strong a resemblance! but this way you can see the commonality). I'd have liked to support for D in Period loop ... but "array type required in indexed component" (which I think means that Date_Container needs the Constant_Indexing aspect?). Running this test just now, with Date_Iteration; with Ada.Calendar.Formatting; with Ada.Text_IO; use Ada.Text_IO; procedure Date_Iteration_Test is use type Ada.Calendar.Time; Period : Date_Iteration.Date_Container; Day : constant Duration := 86_400.0; begin Period.Initialize (Start_Time => Ada.Calendar.Clock, End_Time => Ada.Calendar.Clock + Day * 10, Interval => Day / 2); for C in Period.Iterate loop Put_Line (Ada.Calendar.Formatting.Image (Date_Iteration.Element (C))); end loop; end Date_Iteration_Test; I got $ ./date_iteration_test 2015-11-02 17:35:03 2015-11-03 05:35:03 2015-11-03 17:35:03 2015-11-04 05:35:03 2015-11-04 17:35:03 2015-11-05 05:35:03 2015-11-05 17:35:03 2015-11-06 05:35:03 2015-11-06 17:35:03 2015-11-07 05:35:03 2015-11-07 17:35:03 2015-11-08 05:35:03 2015-11-08 17:35:03 2015-11-09 05:35:03 2015-11-09 17:35:03 2015-11-10 05:35:03 2015-11-10 17:35:03 2015-11-11 05:35:03 2015-11-11 17:35:03 2015-11-12 05:35:03 2015-11-12 17:35:03 ======================================================================== with Ada.Calendar; with Ada.Iterator_Interfaces; package Date_Iteration is type Date_Container is tagged private with Default_Iterator => Iterate, Iterator_Element => Ada.Calendar.Time; procedure Initialize (D : out Date_Container; Start_Time : Ada.Calendar.Time; End_Time : Ada.Calendar.Time; Interval : Duration := 86_400.0); type Cursor is private; No_Element : constant Cursor; function First (Container : Date_Container) return Cursor; function Next (Position : Cursor) return Cursor; function Element (Position : Cursor) return Ada.Calendar.Time; function Has_Element (C : Cursor) return Boolean; package Iterator_Interfaces is new Ada.Iterator_Interfaces (Cursor, Has_Element); function Iterate (Container : Date_Container) return Iterator_Interfaces.Forward_Iterator'Class; private type Date_Container is tagged record Start_Time : Ada.Calendar.Time; End_Time : Ada.Calendar.Time; Interval : Duration; end record; type Date_Container_Access is access all Date_Container; for Date_Container_Access'Storage_Size use 0; type Cursor is record Container : Date_Container_Access; Index : Ada.Calendar.Time; end record; No_Element : constant Cursor := (Container => null, Index => Ada.Calendar.Clock); type Iterator is new Iterator_Interfaces.Forward_Iterator with record Container : Date_Container_Access; end record; overriding function First (Object : Iterator) return Cursor; overriding function Next (Object : Iterator; Position : Cursor) return Cursor; end Date_Iteration; package body Date_Iteration is procedure Initialize (D : out Date_Container; Start_Time : Ada.Calendar.Time; End_Time : Ada.Calendar.Time; Interval : Duration := 86_400.0) is begin D := (Start_Time => Start_Time, End_Time => End_Time, Interval => Interval); end; function First (Container : Date_Container) return Cursor is begin return C : Cursor do C.Container := Container'Unrestricted_Access; C.Index := Container.Start_Time; end return; end First; function Next (Position : Cursor) return Cursor is use type Ada.Calendar.Time; begin if Position.Container = null then return No_Element; end if; return C : Cursor do C.Container := Position.Container; C.Index := Position.Index + Position.Container.Interval; end return; end Next; function Element (Position : Cursor) return Ada.Calendar.Time is (Position.Index); function Has_Element (C : Cursor) return Boolean is use type Ada.Calendar.Time; begin return C.Index <= C.Container.End_Time; end Has_Element; function Iterate (Container : Date_Container) return Iterator_Interfaces.Forward_Iterator'Class is begin return It : Iterator do It.Container := Container'Unrestricted_Access; end return; end Iterate; function First (Object : Iterator) return Cursor is begin return Object.Container.First; end First; function Next (Object : Iterator; Position : Cursor) return Cursor is begin if Position.Container = null then return No_Element; end if; if Position.Container /= Object.Container then raise Program_Error with "container/cursor mismatch"; end if; return Next (Position); end Next; end Date_Iteration; ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-02 17:45 ` Simon Wright @ 2015-11-02 18:48 ` Simon Wright 2015-11-03 6:33 ` Randy Brukardt 2015-11-03 6:40 ` Randy Brukardt 1 sibling, 1 reply; 73+ messages in thread From: Simon Wright @ 2015-11-02 18:48 UTC (permalink / raw) Simon Wright <simon@pushface.org> writes: > I'd have liked to support > > for D in Period loop Oops, I meant "for D of Period", i.e. for D : Ada.Calendar.Time of Period loop ... but you'd need function Constant_Reference (Container : aliased Date_Container; Position : Cursor) return Constant_Reference_Type; returning type Constant_Reference_Type (Element : not null access constant Ada.Calendar.Time) is private with Implicit_Dereference => Element; which is clearly meant for actual containers and here would require - I think - allocating an Ada.Calendar.Time, and of course freeing it eventually. Shame, it makes it tricky to support lazy evaluation. But perhaps we shouldn't want to ... ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-02 18:48 ` Simon Wright @ 2015-11-03 6:33 ` Randy Brukardt 2015-11-03 8:26 ` Simon Wright 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-03 6:33 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:ly1tc8me4w.fsf@pushface.org... > Simon Wright <simon@pushface.org> writes: > >> I'd have liked to support >> >> for D in Period loop > > Oops, I meant "for D of Period", i.e. > > for D : Ada.Calendar.Time of Period loop > ... > > but you'd need > > function Constant_Reference > (Container : aliased Date_Container; > Position : Cursor) return Constant_Reference_Type; > > returning > > type Constant_Reference_Type > (Element : not null access constant Ada.Calendar.Time) is private > with > Implicit_Dereference => Element; > > which is clearly meant for actual containers and here would require - I > think - allocating an Ada.Calendar.Time, and of course freeing it > eventually. > > Shame, it makes it tricky to support lazy evaluation. But perhaps we > shouldn't want to ... If you *only* need constants, the Constant_Indexing function can be a normal function (no implicit dereference required). In that case, the implementation will do the memory management. Note the difference in wording between 4.1.6(2/3) and 4.1.6(3/3) (there is no requirement on the return type for Constant_Indexing). OTOH, I think GNAT got that wrong somehow when I constructed an ACATS test to try that (don't recall the details). So it may not work in your copy of GNAT, most likely it will in a future version. Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-03 6:33 ` Randy Brukardt @ 2015-11-03 8:26 ` Simon Wright 0 siblings, 0 replies; 73+ messages in thread From: Simon Wright @ 2015-11-03 8:26 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Simon Wright" <simon@pushface.org> wrote in message >> function Constant_Reference >> (Container : aliased Date_Container; >> Position : Cursor) return Constant_Reference_Type; >> >> returning >> >> type Constant_Reference_Type >> (Element : not null access constant Ada.Calendar.Time) is private >> with >> Implicit_Dereference => Element; > If you *only* need constants, the Constant_Indexing function can be a > normal function (no implicit dereference required). In that case, the > implementation will do the memory management. Note the difference in > wording between 4.1.6(2/3) and 4.1.6(3/3) (there is no requirement on > the return type for Constant_Indexing). Worked a treat! > OTOH, I think GNAT got that wrong somehow when I constructed an ACATS > test to try that (don't recall the details). So it may not work in > your copy of GNAT, most likely it will in a future version. No problem (for the constant case) with GCC 5.1.0 or GNAT GPL 2015. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-02 17:45 ` Simon Wright 2015-11-02 18:48 ` Simon Wright @ 2015-11-03 6:40 ` Randy Brukardt 2015-11-03 8:34 ` Simon Wright 1 sibling, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-03 6:40 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:ly611kmh1g.fsf@pushface.org... ... > I wrote the attached, using generalized iteration, which bears a strong > resemblance to the standard container iteration (the names bear too > strong a resemblance! but this way you can see the commonality). I suspect you could have written this in a lot simpler fashion. Something similar to the Prime_Numbers iterator found in the ACATS foundation (F552A00, look in the support subdirectory, specifically http://www.ada-auth.org/cgi-bin/cvsweb.cgi/acats/support/f552a00.a) would be a starting point. (Thanks again to Brad Moore for creating this foundation and the associated ACATS tests to give all Ada implementers something to use as a correct example of iterators.) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-03 6:40 ` Randy Brukardt @ 2015-11-03 8:34 ` Simon Wright 2015-11-04 16:19 ` Simon Wright 0 siblings, 1 reply; 73+ messages in thread From: Simon Wright @ 2015-11-03 8:34 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Simon Wright" <simon@pushface.org> wrote in message > news:ly611kmh1g.fsf@pushface.org... > ... >> I wrote the attached, using generalized iteration, which bears a >> strong resemblance to the standard container iteration (the names >> bear too strong a resemblance! but this way you can see the >> commonality). > > I suspect you could have written this in a lot simpler > fashion. Something similar to the Prime_Numbers iterator found in the > ACATS foundation (F552A00, look in the support subdirectory, > specifically > http://www.ada-auth.org/cgi-bin/cvsweb.cgi/acats/support/f552a00.a) > would be a starting point. (Thanks again to Brad Moore for creating > this foundation and the associated ACATS tests to give all Ada > implementers something to use as a correct example of iterators.) Great pointer. Though I think the Date case would be a bit more complicated, because you couldn't constrain a Date_Set by Times or Durations. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-03 8:34 ` Simon Wright @ 2015-11-04 16:19 ` Simon Wright 2015-11-05 1:20 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: Simon Wright @ 2015-11-04 16:19 UTC (permalink / raw) Simon Wright <simon@pushface.org> writes: > "Randy Brukardt" <randy@rrsoftware.com> writes: > >> "Simon Wright" <simon@pushface.org> wrote in message >> news:ly611kmh1g.fsf@pushface.org... >> ... >>> I wrote the attached, using generalized iteration, which bears a >>> strong resemblance to the standard container iteration (the names >>> bear too strong a resemblance! but this way you can see the >>> commonality). >> >> I suspect you could have written this in a lot simpler >> fashion. Something similar to the Prime_Numbers iterator found in the >> ACATS foundation (F552A00, look in the support subdirectory, >> specifically >> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/acats/support/f552a00.a) >> would be a starting point. (Thanks again to Brad Moore for creating >> this foundation and the associated ACATS tests to give all Ada >> implementers something to use as a correct example of iterators.) > > Great pointer. Though I think the Date case would be a bit more > complicated, because you couldn't constrain a Date_Set by Times or > Durations. And I was hoping to write with Ada.Text_IO; with F552A00_Prime_Numbers; procedure Primes is begin for P of F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop Ada.Text_IO.Put_Line (P'Img); end loop; end Primes; but (surprise) primes.adb:5:08: cannot iterate over "Prime_Number_Set" ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-04 16:19 ` Simon Wright @ 2015-11-05 1:20 ` Randy Brukardt 2015-11-05 8:34 ` briot.emmanuel 2015-11-05 8:45 ` Simon Wright 0 siblings, 2 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-05 1:20 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:lybnb9lote.fsf@pushface.org... > Simon Wright <simon@pushface.org> writes: > >> "Randy Brukardt" <randy@rrsoftware.com> writes: >> >>> "Simon Wright" <simon@pushface.org> wrote in message >>> news:ly611kmh1g.fsf@pushface.org... >>> ... >>>> I wrote the attached, using generalized iteration, which bears a >>>> strong resemblance to the standard container iteration (the names >>>> bear too strong a resemblance! but this way you can see the >>>> commonality). >>> >>> I suspect you could have written this in a lot simpler >>> fashion. Something similar to the Prime_Numbers iterator found in the >>> ACATS foundation (F552A00, look in the support subdirectory, >>> specifically >>> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/acats/support/f552a00.a) >>> would be a starting point. (Thanks again to Brad Moore for creating >>> this foundation and the associated ACATS tests to give all Ada >>> implementers something to use as a correct example of iterators.) >> >> Great pointer. Though I think the Date case would be a bit more >> complicated, because you couldn't constrain a Date_Set by Times or >> Durations. > > And I was hoping to write > > with Ada.Text_IO; > with F552A00_Prime_Numbers; > procedure Primes is > begin > for P of F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) > loop > Ada.Text_IO.Put_Line (P'Img); > end loop; > end Primes; > > but (surprise) > > primes.adb:5:08: cannot iterate over "Prime_Number_Set" Prime_Number_Set is (directly) an iterator, so you use "in" to iterate over it: for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop The "of" form is for iterating over an array or a container whose type has the Default_Iterator aspect (which gives the iterator to use). I can hear the head slap from here. ;-) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-05 1:20 ` Randy Brukardt @ 2015-11-05 8:34 ` briot.emmanuel 2015-11-12 18:28 ` Randy Brukardt 2015-11-05 8:45 ` Simon Wright 1 sibling, 1 reply; 73+ messages in thread From: briot.emmanuel @ 2015-11-05 8:34 UTC (permalink / raw) > The "of" form is for iterating over an array or a container whose type has > the Default_Iterator aspect (which gives the iterator to use). The main drawback, though, is that you then get a Cursor, not an Element, so you still need to call the functions Element or Reference to get to the actual element. This is slightly less convenient (syntax-wise). I wish it was possible to use "of" to indicate that we want to get an element, even when the right-side is an iterator (which for instance would be convenient when writing graph data structures where there really are lots of different ways to iterate, and a single Default_Iterator is not enough ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-05 8:34 ` briot.emmanuel @ 2015-11-12 18:28 ` Randy Brukardt 2015-11-12 20:19 ` Simon Wright ` (2 more replies) 0 siblings, 3 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-12 18:28 UTC (permalink / raw) <briot.emmanuel@gmail.com> wrote in message news:aa0cf839-651e-494d-a826-c2ce31a7afd3@googlegroups.com... >> The "of" form is for iterating over an array or a container whose type >> has >> the Default_Iterator aspect (which gives the iterator to use). > > The main drawback, though, is that you then get a Cursor, not an Element, > so > you still need to call the functions Element or Reference to get to the > actual > element. This is slightly less convenient (syntax-wise). Sure, but not in a case like the OP's, where the "cursor" is the actual data and there is no element. In that case, "of" is just overkill. > I wish it was possible > to use "of" to indicate that we want to get an element, even when the > right-side is an iterator (which for instance would be convenient when > writing graph data structures where there really are lots of different > ways > to iterate, and a single Default_Iterator is not enough That doesn't make sense, though, as the iterator interface doesn't contain the information necessary to do "of" iteration. In particular, it doesn't provide the container or Reference function -- nor could it, as there may not be a container. Personally, I find the "of" form unnecessary; we've iterated arrays for decades without direct access to the element (using the "cursor", that is the array index), so why are containers different? Especially as the indexing form works on all of the language-defined containers (you never need to explicitly call Reference or Element). So an "in" iterator looks just like the array iteration that we've been using from the beginning of time. What's so hard about that? Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 18:28 ` Randy Brukardt @ 2015-11-12 20:19 ` Simon Wright 2015-11-12 20:56 ` Dmitry A. Kazakov 2015-11-13 8:45 ` briot.emmanuel 2 siblings, 0 replies; 73+ messages in thread From: Simon Wright @ 2015-11-12 20:19 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > <briot.emmanuel@gmail.com> wrote in message > news:aa0cf839-651e-494d-a826-c2ce31a7afd3@googlegroups.com... >>> The "of" form is for iterating over an array or a container whose >>> type has the Default_Iterator aspect (which gives the iterator to >>> use). >> >> The main drawback, though, is that you then get a Cursor, not an >> Element, so you still need to call the functions Element or Reference >> to get to the actual element. This is slightly less convenient >> (syntax-wise). > > Sure, but not in a case like the OP's, where the "cursor" is the > actual data and there is no element. In that case, "of" is just > overkill. There's one problem for Times; how to determine when to end the loop if the cursor is the actual data? I ended up with type Cursor (Valid : Boolean := True) is record case Valid is when True => Date : Ada.Calendar.Time; when False => null; end case; end record; where both First and Next set Valid to False if the iteration has ended. I spent a lot too much time without giving Valid a default value; there is an assignment, but it's hidden inside the generated code, so at the end of the loop the discriminant changes ... I think this may be related to the way that F552A00_Prime_Numbers doesn't support an upper bound of 2; the loop terminates when Is_Prime returns false, and of course 2 + 1 = 3 which .. Is_Prime. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 18:28 ` Randy Brukardt 2015-11-12 20:19 ` Simon Wright @ 2015-11-12 20:56 ` Dmitry A. Kazakov 2015-11-12 21:15 ` Randy Brukardt 2015-11-13 8:45 ` briot.emmanuel 2 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-12 20:56 UTC (permalink / raw) On Thu, 12 Nov 2015 12:28:46 -0600, Randy Brukardt wrote: > Personally, I find the "of" form unnecessary; we've iterated arrays for > decades without direct access to the element (using the "cursor", that is > the array index), so why are containers different? Of course it is different. Index does not iterate array, it does the array's index range. That is the difference. You can iterate elements of a container or indices of a container. It is not same. > Especially as the > indexing form works on all of the language-defined containers (you never > need to explicitly call Reference or Element). So an "in" iterator looks > just like the array iteration that we've been using from the beginning of > time. What's so hard about that? There could be cases when a container does not have any natural index. E.g. a bag, a set, a files directory etc. You could iterate elements of without inventing indices. Especially when the index is volatile. Consider an implementation that gets a result set of a DB query and then iterates the result. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 20:56 ` Dmitry A. Kazakov @ 2015-11-12 21:15 ` Randy Brukardt 2015-11-13 8:40 ` Dmitry A. Kazakov 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-12 21:15 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:hs9mu83acmqt$.5liwfglzrr7q.dlg@40tude.net... > On Thu, 12 Nov 2015 12:28:46 -0600, Randy Brukardt wrote: > >> Personally, I find the "of" form unnecessary; we've iterated arrays for >> decades without direct access to the element (using the "cursor", that is >> the array index), so why are containers different? > > Of course it is different. Index does not iterate array, it does the > array's index range. That is the difference. > > You can iterate elements of a container or indices of a container. It is > not same. Surely it is not the same. But why do we need the first? An array is surely a container, and we got along just fine for 30 years without being able to iterate elements of arrays. There is absolutely no difference for any other sort of container (especially as the array syntax can be used for any container). Iterating on elements of a container is unnecessary overkill. (It's also harmless overkill, unlike, say, anonymous access types). >> Especially as the >> indexing form works on all of the language-defined containers (you never >> need to explicitly call Reference or Element). So an "in" iterator looks >> just like the array iteration that we've been using from the beginning of >> time. What's so hard about that? > > There could be cases when a container does not have any natural index. > E.g. > a bag, a set, a files directory etc. You could iterate elements of without > inventing indices. Especially when the index is volatile. Consider an > implementation that gets a result set of a DB query and then iterates the > result. There is always *something* that works as an index. If there isn't, you can't iterate (because you can't figure out a reproducible order for which item is next). In any case, Ada does not support iteration without something being a cursor; the "of" form of iteration is a direct translation of the "in" form of iteration (it's purely syntactic with no semantics of its own). Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 21:15 ` Randy Brukardt @ 2015-11-13 8:40 ` Dmitry A. Kazakov 2015-11-13 17:52 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-13 8:40 UTC (permalink / raw) On Thu, 12 Nov 2015 15:15:45 -0600, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:hs9mu83acmqt$.5liwfglzrr7q.dlg@40tude.net... >> On Thu, 12 Nov 2015 12:28:46 -0600, Randy Brukardt wrote: >> >>> Personally, I find the "of" form unnecessary; we've iterated arrays for >>> decades without direct access to the element (using the "cursor", that is >>> the array index), so why are containers different? >> >> Of course it is different. Index does not iterate array, it does the >> array's index range. That is the difference. >> >> You can iterate elements of a container or indices of a container. It is >> not same. > > Surely it is not the same. But why do we need the first? For doing this: for Line in Read (Text_File) loop ... end loop; Operation Read provides an iterateable container-view of Text_File. There cannot be any index, because the "buffer" will contain just single line. Providing index will be error-prone and cause run-time overhead (index checks). Add here naming issues, you need a name for the container-view: for Line_No in Read (Text_File) loop declare Next_Line : String := ??? (Index + 1); -- Oops! begin ... end; end loop; An array interface would promise more than there actually is. It would be bad design. > An array is surely > a container, and we got along just fine for 30 years without being able to > iterate elements of arrays. Not every container is an array. There are lots of containers which semantically have no index. > There is absolutely no difference for any other > sort of container (especially as the array syntax can be used for any > container). It cannot be, e.g. for a general case graph, but that is another story. > Iterating on elements of a container is unnecessary overkill. (It's also > harmless overkill, unlike, say, anonymous access types). > >>> Especially as the >>> indexing form works on all of the language-defined containers (you never >>> need to explicitly call Reference or Element). So an "in" iterator looks >>> just like the array iteration that we've been using from the beginning of >>> time. What's so hard about that? >> >> There could be cases when a container does not have any natural index. E.g. >> a bag, a set, a files directory etc. You could iterate elements of without >> inventing indices. Especially when the index is volatile. Consider an >> implementation that gets a result set of a DB query and then iterates the >> result. > > There is always *something* that works as an index. If there isn't, you > can't iterate (because you can't figure out a reproducible order for which > item is next). First, index is more than iteration. Index assumes random access and an ability to access any number of times. Iteration requires only sequential access and only visit once. If you equate both, you either burden the implementation with unnecessary functionality or the clients in order to catch unsupported actions. Not good. Secondly, it is an implementation driven view. The problem space may have no index even when the implementation could have one. Exposing implementation details is bad. > In any case, Ada does not support iteration without something > being a cursor; the "of" form of iteration is a direct translation of the > "in" form of iteration (it's purely syntactic with no semantics of its own). Yes, Ada has a lot of issues with abstract interfaces. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 8:40 ` Dmitry A. Kazakov @ 2015-11-13 17:52 ` Randy Brukardt 2015-11-13 20:37 ` Dmitry A. Kazakov 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-13 17:52 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:1dolqizyi8gxi.t3173bhifuu1.dlg@40tude.net... > On Thu, 12 Nov 2015 15:15:45 -0600, Randy Brukardt wrote: ... >> Surely it is not the same. But why do we need the first? > > For doing this: > > for Line in Read (Text_File) loop > ... > end loop; Note that you used "in" rather than "of" here. And if you did that, there is no problem implementing this in the existing Ada, even as you suggest. ... > Operation Read provides an iterateable container-view of Text_File. There > cannot be any index, because the "buffer" will contain just single line. A "cursor" is not necessarily an array index, as I pointed out earlier in this thread. For anything "on demand", the cursor probably ought to be the data itself. (You'd probably have to use an unbounded string for that, but that's a different problem unrelated to iteration.) ... >> An array is surely >> a container, and we got along just fine for 30 years without being able >> to >> iterate elements of arrays. > > Not every container is an array. There are lots of containers which > semantically have no index. Then provide an iterator implementation where the cursor is an access to the element. ... >> There is always *something* that works as an index. If there isn't, you >> can't iterate (because you can't figure out a reproducible order for >> which >> item is next). > > First, index is more than iteration. Index assumes random access and an > ability to access any number of times. Iteration requires only sequential > access and only visit once. If you equate both, you either burden the > implementation with unnecessary functionality or the clients in order to > catch unsupported actions. Not good. You are giving more properties than necessary to an iteration cursor (which is what we are talking about). There is absolutely no problem with it providing sequential one-time access. You have to program it that way, of course, but it's not hard to do (see the implementation in the ACATS, for one example). I might have confused you by calling it an "index", because it's clear that you're assigning properties to it that I am not. There's no reason that you have to use a for loop parameter as an index! (I often write traditional loops where the loop parameter is not an index.) > Secondly, it is an implementation driven view. The problem space may have > no index even when the implementation could have one. Exposing > implementation details is bad. That's the Bag arrgument again. I think that particular data structure is a fraud, because it cannot be created in practice -- plus you have to have some sort of access to the elements, so you end up with a cursor of some sort anyway. There's a reason there is no Bag in the Ada.Containers library! Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 17:52 ` Randy Brukardt @ 2015-11-13 20:37 ` Dmitry A. Kazakov 2015-11-13 22:15 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-13 20:37 UTC (permalink / raw) On Fri, 13 Nov 2015 11:52:29 -0600, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:1dolqizyi8gxi.t3173bhifuu1.dlg@40tude.net... >> On Thu, 12 Nov 2015 15:15:45 -0600, Randy Brukardt wrote: > ... >>> Surely it is not the same. But why do we need the first? >> >> For doing this: >> >> for Line in Read (Text_File) loop >> ... >> end loop; > > Note that you used "in" rather than "of" here. Yes, because Ada always had this syntax for iterating elements of a set. It is: for I in A'Range loop It is not for I in A loop If the later were legal then loop parameter must have been a pair (Index, Element), because that is what an array is: a set of pairs. [ "of" is rubbish of course. It is "in" that iterates / enumerates a set. If "of" should ever be used then for something else. ] > And if you did that, there is > no problem implementing this in the existing Ada, even as you suggest. I am not sure about that. >> Operation Read provides an iterateable container-view of Text_File. There >> cannot be any index, because the "buffer" will contain just single line. > > A "cursor" is not necessarily an array index, as I pointed out earlier in > this thread. Array does not contain "cursors." Cursor is an evil idea, but that is unrelated to the issue of iteration over a general set. >>> An array is surely >>> a container, and we got along just fine for 30 years without being able >>> to iterate elements of arrays. >> >> Not every container is an array. There are lots of containers which >> semantically have no index. > > Then provide an iterator implementation where the cursor is an access to the > element. Why do I need extra data types, bad types as they involve pointers? >>> There is always *something* that works as an index. If there isn't, you >>> can't iterate (because you can't figure out a reproducible order for >>> which >>> item is next). >> >> First, index is more than iteration. Index assumes random access and an >> ability to access any number of times. Iteration requires only sequential >> access and only visit once. If you equate both, you either burden the >> implementation with unnecessary functionality or the clients in order to >> catch unsupported actions. Not good. > > You are giving more properties than necessary to an iteration cursor (which > is what we are talking about). There is absolutely no problem with it > providing sequential one-time access. You have to program it that way, of > course, but it's not hard to do (see the implementation in the ACATS, for > one example). Maybe yes, maybe no. But cursor is neither index nor element. Cursor is same as a pointer. > I might have confused you by calling it an "index", because it's clear that > you're assigning properties to it that I am not. There's no reason that you > have to use a for loop parameter as an index! (I often write traditional > loops where the loop parameter is not an index.) > >> Secondly, it is an implementation driven view. The problem space may have >> no index even when the implementation could have one. Exposing >> implementation details is bad. > > That's the Bag arrgument again. I think that particular data structure is a > fraud, because it cannot be created in practice -- plus you have to have > some sort of access to the elements, so you end up with a cursor of some > sort anyway. No way. The bag is a set that only supports insertion and iteration. Nothing more. It is very useful, e.g. to hold strong references to allocated data. References are thrown into a bag. At some point the bag is iterated and all references invalidated releasing resources. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 20:37 ` Dmitry A. Kazakov @ 2015-11-13 22:15 ` Randy Brukardt 2015-11-14 11:42 ` Dmitry A. Kazakov 2015-11-14 12:37 ` Simon Wright 0 siblings, 2 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-13 22:15 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:1705bpj6jrld0.1lc44o5yo6bj7$.dlg@40tude.net... > On Fri, 13 Nov 2015 11:52:29 -0600, Randy Brukardt wrote: ... >> And if you did that, there is >> no problem implementing this in the existing Ada, even as you suggest. > > I am not sure about that. I am. :-) You'd probably keep some state in the iterator object (some access to the file, at a minimum, possibly a buffer). The "cursor" would be the character. Each call to Next would put the following character into the "cursor". Easy-peasy. :-) Thinking of an iterator "cursor" as having to be some sort of index obscures the real possibilities of the interface. >>> Operation Read provides an iterateable container-view of Text_File. >>> There >>> cannot be any index, because the "buffer" will contain just single line. >> >> A "cursor" is not necessarily an array index, as I pointed out earlier in >> this thread. > > Array does not contain "cursors." Cursor is an evil idea, but that is > unrelated to the issue of iteration over a general set. We're not talking about arrays, we're talking about iteration. And for this purpose, "cursor" could just as well be called "blob". It's a type parameter to the interface, nothing more. One might give it additional semantics for some particular implementation, but that's not inherent in the model. >>>> An array is surely >>>> a container, and we got along just fine for 30 years without being able >>>> to iterate elements of arrays. >>> >>> Not every container is an array. There are lots of containers which >>> semantically have no index. >> >> Then provide an iterator implementation where the cursor is an access to >> the >> element. > > Why do I need extra data types, bad types as they involve pointers? An iterator is an extra data type. And you surely don't need to involve pointers, if copying the element is OK. If you want to modify the element in place, then some sort of pointer is always required (outside of the built-in array type). ... ... >> You are giving more properties than necessary to an iteration cursor >> (which >> is what we are talking about). There is absolutely no problem with it >> providing sequential one-time access. You have to program it that way, of >> course, but it's not hard to do (see the implementation in the ACATS, for >> one example). > > Maybe yes, maybe no. But cursor is neither index nor element. Cursor is > same as a pointer. Definitely not, in the iterator interface. It is anything you want it to be. Surely, for discrete unmodifiable values, it's better that the "cursor" be directly that value. (The read from a file example, the prime numbers example, and the OPs example all have this property.) "Cursor" is just the name of the type in the generic interface. Just because it has that name (and is commonly used as an index), doesn't mean that it always has to be used that way. ... >> That's the Bag arrgument again. I think that particular data structure is >> a >> fraud, because it cannot be created in practice -- plus you have to have >> some sort of access to the elements, so you end up with a cursor of some >> sort anyway. > > No way. The bag is a set that only supports insertion and iteration. > Nothing more. It is very useful, e.g. to hold strong references to > allocated data. References are thrown into a bag. At some point the bag is > iterated and all references invalidated releasing resources. Your description points out the problem: it's "a set", at which point a set implementation is appropriate. And the implementation is identical to any other set, so there is almost no value to having a separate bag implementation (it provides no performance improvements over an ordered set, for instance). Whether its useful or not is irrelevant -- it is indistiguishable from any other set (the extra operations having no effect or overhead if not used). So there is no real value to having a separate Bag abstraction. Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 22:15 ` Randy Brukardt @ 2015-11-14 11:42 ` Dmitry A. Kazakov 2015-11-14 12:37 ` Simon Wright 1 sibling, 0 replies; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-14 11:42 UTC (permalink / raw) On Fri, 13 Nov 2015 16:15:01 -0600, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:1705bpj6jrld0.1lc44o5yo6bj7$.dlg@40tude.net... >> On Fri, 13 Nov 2015 11:52:29 -0600, Randy Brukardt wrote: > ... >>> And if you did that, there is >>> no problem implementing this in the existing Ada, even as you suggest. >> >> I am not sure about that. > > I am. :-) > > You'd probably keep some state in the iterator object (some access to the > file, at a minimum, possibly a buffer). The "cursor" would be the character. > Each call to Next would put the following character into the "cursor". > Easy-peasy. :-) It would be nice to see a demonstration for iterating lines of a text file... (:-)) >>>>> An array is surely >>>>> a container, and we got along just fine for 30 years without being able >>>>> to iterate elements of arrays. >>>> >>>> Not every container is an array. There are lots of containers which >>>> semantically have no index. >>> >>> Then provide an iterator implementation where the cursor is an access to >>> the element. >> >> Why do I need extra data types, bad types as they involve pointers? > > An iterator is an extra data type. And you surely don't need to involve > pointers, if copying the element is OK. And a pointer to the container. >>> That's the Bag arrgument again. I think that particular data structure is a >>> fraud, because it cannot be created in practice -- plus you have to have >>> some sort of access to the elements, so you end up with a cursor of some >>> sort anyway. >> >> No way. The bag is a set that only supports insertion and iteration. >> Nothing more. It is very useful, e.g. to hold strong references to >> allocated data. References are thrown into a bag. At some point the bag is >> iterated and all references invalidated releasing resources. > > Your description points out the problem: it's "a set", at which point a set > implementation is appropriate. And the implementation is identical to any > other set, so there is almost no value to having a separate bag > implementation (it provides no performance improvements over an ordered set, > for instance). A bag need not to be sorted, no overhead to keep the order, no need for elements to have "=" and "<". > Whether its useful or not is irrelevant -- it is indistiguishable from any > other set (the extra operations having no effect or overhead if not used). It is. The implementation will likely choose a singly linked list of element buckets. > So there is no real value to having a separate Bag abstraction. Even if the implementation were same, abstraction is called abstraction because it is not implementation. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 22:15 ` Randy Brukardt 2015-11-14 11:42 ` Dmitry A. Kazakov @ 2015-11-14 12:37 ` Simon Wright 2015-11-14 17:24 ` Shark8 2015-11-15 18:54 ` Brad Moore 1 sibling, 2 replies; 73+ messages in thread From: Simon Wright @ 2015-11-14 12:37 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > You'd probably keep some state in the iterator object (some access to > the file, at a minimum, possibly a buffer). The "cursor" would be the > character. Each call to Next would put the following character into > the "cursor". Easy-peasy. :-) It's a pity that Next takes the iterator object as an 'in' parameter. This means that, in general, the cursor needs to hold the state. It certainly needs some way of indicating end-of-iteration; perhaps a sentinel value. Can I use the same iterator more than once? (so long as the container hasn't changed, of course - I expect that would count as tampering, though) If so, that'd explain why Next.Object is an in parameter! ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-14 12:37 ` Simon Wright @ 2015-11-14 17:24 ` Shark8 2015-11-14 20:09 ` Simon Wright 2015-11-15 18:54 ` Brad Moore 1 sibling, 1 reply; 73+ messages in thread From: Shark8 @ 2015-11-14 17:24 UTC (permalink / raw) On Saturday, November 14, 2015 at 5:37:32 AM UTC-7, Simon Wright wrote: > > It's a pity that Next takes the iterator object as an 'in' > parameter. This means that, in general, the cursor needs to hold the > state. It certainly needs some way of indicating end-of-iteration; > perhaps a sentinel value. Sentinel values, or exceptions? C-style strings use ASCII.NUL as a sentinel value, and look at the trouble that causes. (Of course part of that is due to the anemic idea of arrays that C has.) ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-14 17:24 ` Shark8 @ 2015-11-14 20:09 ` Simon Wright 0 siblings, 0 replies; 73+ messages in thread From: Simon Wright @ 2015-11-14 20:09 UTC (permalink / raw) Shark8 <onewingedshark@gmail.com> writes: > On Saturday, November 14, 2015 at 5:37:32 AM UTC-7, Simon Wright wrote: >> >> It's a pity that Next takes the iterator object as an 'in' >> parameter. This means that, in general, the cursor needs to hold the >> state. It certainly needs some way of indicating end-of-iteration; >> perhaps a sentinel value. > > Sentinel values, or exceptions? C-style strings use ASCII.NUL as a > sentinel value, and look at the trouble that causes. (Of course part > of that is due to the anemic idea of arrays that C has.) Next (Iterator, Cursor) return Cursor is the operation that would detect End_Of_File or whatever and indicate in the result Cursor that the iteration had ended. Although it would indeed quit the loop, I don't think using an exception would be good (especially in a restricted runtime without exception propagation). If no sentinel value is possible, you're stuck (I think) with type Cursor (Running : Boolean := True) is record case Running is when True => Element : Whatever; when False => null; end case; end record; ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-14 12:37 ` Simon Wright 2015-11-14 17:24 ` Shark8 @ 2015-11-15 18:54 ` Brad Moore 1 sibling, 0 replies; 73+ messages in thread From: Brad Moore @ 2015-11-15 18:54 UTC (permalink / raw) On Saturday, November 14, 2015 at 5:37:32 AM UTC-7, Simon Wright wrote: > "Randy Brukardt" <randy@rrsoftware.com> writes: > > > You'd probably keep some state in the iterator object (some access to > > the file, at a minimum, possibly a buffer). The "cursor" would be the > > character. Each call to Next would put the following character into > > the "cursor". Easy-peasy. :-) > > It's a pity that Next takes the iterator object as an 'in' > parameter. This means that, in general, the cursor needs to hold the > state. It certainly needs some way of indicating end-of-iteration; > perhaps a sentinel value. I found this to be a problem also. I have been working on an AI to potentially add iterators to Ada.Directories and Ada.Environment_Variables for consideration for Ada 202x (Ada 2019?). I was able to get a working implementation using both an Iterator approach, and an Iterable container approach. So far the Iterable container approach seems like a better choice here because it lets the programmer choose between either "in" or "of" syntax for the loops. With the Iterator approach, you can only use "in" loops, although that's really not a big deal, in my opinion. For both of these approaches, I found I also needed "in out" parameters for these interfaces. In fact, looking at my iterable container implementation it appears that First, Next, and Iterate all need to have 'in out' parameters. For Ada.Directories, it made sense to have the container contain a Search_Type component, and the Iterator type to contain a Directory_Entry component, which contains the current directory entry for the loop. The Next function needs to update its Directory_Entry component to get the next directory entry, so it needs read-write access. I was able to work around this by using the Rosen trick to acquire read-write access to the "in" parameters for these functions. However, this is awkward, and it tells me that we have the wrong interfaces for iterators, or at least we have missing interfaces. One shouldn't have to jump through such hoops to write iterators for abstract data types. Brad > > Can I use the same iterator more than once? (so long as the container > hasn't changed, of course - I expect that would count as tampering, > though) If so, that'd explain why Next.Object is an in parameter! ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 18:28 ` Randy Brukardt 2015-11-12 20:19 ` Simon Wright 2015-11-12 20:56 ` Dmitry A. Kazakov @ 2015-11-13 8:45 ` briot.emmanuel 2015-11-13 17:41 ` Randy Brukardt 2 siblings, 1 reply; 73+ messages in thread From: briot.emmanuel @ 2015-11-13 8:45 UTC (permalink / raw) On Thursday, November 12, 2015 at 7:28:49 PM UTC+1, Randy Brukardt wrote: > That doesn't make sense, though, as the iterator interface doesn't contain > the information necessary to do "of" iteration. In particular, it doesn't > provide the container or Reference function -- nor could it, as there may > not be a container. Absolutely, we cannot do that with Ada, as defined in the standard. But that's exactly what I am complaining about. The aspects should have been defined on the Iterator, not on the container itself, as in: type Graph is tagged private with Default_Iterator => Depth_First_Search; type DFS_Iterator is private with Reference => Reference, Iterator_Element => Element_Tye; function Depth_First_Search (Self : Graph) return DFS_Iterator; type BFS_Iterator is private with Reference => Reference, Iterator_Element => Element_Tye; function Breadth_First_Search (Self : Graph) return BFS_Iterator; With such a separation, I could then do something like: G : Graph; for E of G loop -- depth first search null; end loop; for E of G.Breadth_First_Search loop -- breadth first search, get element null; end loop; for C in G.Breadth_First_Search loop -- breadth first search, get cursor null; end loop; The aspects were put at the wrong level, and iterators end up being hidden magical objects, rather than first class citizens with their own role in the design of containers. > Personally, I find the "of" form unnecessary; we've iterated arrays for > decades without direct access to the element (using the "cursor", that is > the array index), so why are containers different? Especially as the > indexing form works on all of the language-defined containers (you never > need to explicitly call Reference or Element). So an "in" iterator looks > just like the array iteration that we've been using from the beginning of > time. What's so hard about that? There are lots of things we have been doing for decades. We have been inserting explicit tests and asserts, and now we are adding pre and post conditions, just to find one example. Languages evolve, as you well know of course, and the goal is to make them more expressive. I like to clearly state what I mean in the code, but on the other hand why should I have to specify "Element (C)" when I can just use "E" ? ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 8:45 ` briot.emmanuel @ 2015-11-13 17:41 ` Randy Brukardt 2015-11-14 19:57 ` briot.emmanuel 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-13 17:41 UTC (permalink / raw) <briot.emmanuel@gmail.com> wrote in message news:db3ea03a-07cc-4f1a-96aa-a7a18d5e2145@googlegroups.com... > On Thursday, November 12, 2015 at 7:28:49 PM UTC+1, Randy Brukardt wrote: >> That doesn't make sense, though, as the iterator interface doesn't >> contain >> the information necessary to do "of" iteration. In particular, it doesn't >> provide the container or Reference function -- nor could it, as there may >> not be a container. > > Absolutely, we cannot do that with Ada, as defined in the standard. But > that's > exactly what I am complaining about. The aspects should have been defined > on the Iterator, not on the container itself, as in: > > type Graph is tagged private > with Default_Iterator => Depth_First_Search; > > type DFS_Iterator is private > with Reference => Reference, > Iterator_Element => Element_Tye; > function Depth_First_Search (Self : Graph) return DFS_Iterator; > > type BFS_Iterator is private > with Reference => Reference, > Iterator_Element => Element_Tye; > function Breadth_First_Search (Self : Graph) return BFS_Iterator; > > With such a separation, I could then do something like: No, you couldn't, because there still is no way for the compiler to identify the container to pass to the Reference aspect. If you mean to magically extract it from the call to Depth_First_Search, I would be strongly against as there is no need for an actual container object for an iterator (and the model specifically was designed to allow that possibility). It would be *much* more limiting to assume a container. I suppose you could add a third aspect to specify which parameter is the container, and then use additional magic to add a renames of that parameter (with all of the attendant restrictions on what that parameter could be). Definitely a lot more complicated than what we have (and what we have is too complicated). > for E of G.Breadth_First_Search loop -- breadth first search, get > element > null; > end loop; Again, how does the compiler know that G is the container in this iterator? "G.Breadth_First_Search" is just a function call. On top of which, you now have two different and unrelated expected types for the iterator, which would be a new concept in Ada. > The aspects were put at the wrong level, and iterators end up being hidden > magical objects, rather than first class citizens with their own role in > the > design of containers. Well, I disagree. The iterators are certainly a first-class type, so long as you use the "in" form. And it's impossible to use the "of" form for all possible iterations; it's way too limiting for the general case. >> Personally, I find the "of" form unnecessary; we've iterated arrays for >> decades without direct access to the element (using the "cursor", that is >> the array index), so why are containers different? Especially as the >> indexing form works on all of the language-defined containers (you never >> need to explicitly call Reference or Element). So an "in" iterator looks >> just like the array iteration that we've been using from the beginning of >> time. What's so hard about that? > > There are lots of things we have been doing for decades. We have been > inserting explicit tests and asserts, and now we are adding pre and post > conditions, just to find one example. Languages evolve, as you well know > of course, and the goal is to make them more expressive. Umm, no, the goal is to provide new capabilities to allow Ada to solve additional problems. (Pre and Post are definitely new capabilities - see the class-wide versions and 'Old; pragma Assert was too much of a blunt instrument to be of much use.) Making a language "more expressive" is code for "easier to write", which never was a goal of Ada. To the extent that we've made the language "more expressive", it's been to make ADTs more like the capabilities of the built-in types (for instance, arrays). Going beyond that is unnecessary and probably harmful. > I like to clearly > state what I mean in the code, but on the other hand why should I have > to specify "Element (C)" when I can just use "E" ? Readability, of course. I don't believe that you should ever have been allowed to just specify E. I lost that argument 'cause it wasn't sufficiently evil to waste scarce political capital on, but I don't see any reason to expand the evil, or worry because it doesn't work in some cases. (That was clearly understood when we defined it; it was intended to be a quicky shorthand, not the way to do most iterations.) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-13 17:41 ` Randy Brukardt @ 2015-11-14 19:57 ` briot.emmanuel 2015-11-16 19:13 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: briot.emmanuel @ 2015-11-14 19:57 UTC (permalink / raw) > No, you couldn't, because there still is no way for the compiler to identify > the container to pass to the Reference aspect. You seem to be mixing the particular implementation you would use with what the standard should allow. There is nothing in the spec of a reference type that mandates knowing the container (and the way it currently is done in the implementations is to use a 'Unrestricted_Access, which is ugly to say the least). > If you mean to magically extract it from the call to Depth_First_Search, I > would be strongly against as there is no need for an actual container object > for an iterator (and the model specifically was designed to allow that > possibility). It would be *much* more limiting to assume a container. If I want my iterator to implement depth_first_search, it would indeed need to know the container (like most iterators would need to know the container, in fact). The reference type itself (the end product of the iteration) doesn't need to know that though. The container is necessary for the iteration or traversal of itself, but certainly not once you manipulate an element. My example assumed nothing. The implementation you seem to have in your head seems indeed to assume a lot of unnecessary things. > Definitely a lot more complicated than what we have (and what we have is too > complicated). What we have is both too complicated and too limited. Too complicated because nobody that hasn't spent a full week will be able to explain how the aspects combine with iterators to end up with cursors and the for-of loop. They just happen to work for existing containers, but as this thread has proven, anyone who tries to actually implement them for other uses that the few official containers quickly hits sever limitations. > > > for E of G.Breadth_First_Search loop -- breadth first search, get > > element > > null; > > end loop; > > Again, how does the compiler know that G is the container in this iterator? > "G.Breadth_First_Search" is just a function call. On top of which, you now > have two different and unrelated expected types for the iterator, which > would be a new concept in Ada. It is a function call that returns the iterator. So obviously it is allowed to have a relationship between the return value and the parameters. The iterator is therefore allowed (but not mandated, that would depend on the actual container we are talking about) to have a reference to the container. This is called flexibility. Something lacking in the current standard. I do not understand your last sentence about the two unexpected types. > Making a language "more expressive" is code for "easier to write", which > never was a goal of Ada. That's one of the issue here. The goal for Ada, as I understand it, has always been to be "easier to read". There is no reason why "easier to write" should be in opposition to that goal. > > I like to clearly > > state what I mean in the code, but on the other hand why should I have > > to specify "Element (C)" when I can just use "E" ? > > Readability, of course. I don't believe that you should ever have been > allowed to just specify E. I lost that argument 'cause it wasn't > sufficiently evil to waste scarce political capital on, but I don't see any Now I understand. You are re-fighting a fight you lost apparently. But from talking to all my colleagues (all of whom are of course Ada experts), we all much prefer the form with just "E" in practice. So that change was a great improvement in the standard, if not quite wide reaching enough. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-14 19:57 ` briot.emmanuel @ 2015-11-16 19:13 ` Randy Brukardt 2015-11-16 20:47 ` Dmitry A. Kazakov ` (2 more replies) 0 siblings, 3 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-16 19:13 UTC (permalink / raw) <briot.emmanuel@gmail.com> wrote in message news:5007b311-5d2e-448c-b8c8-fc2e2d88ea5e@googlegroups.com... >> No, you couldn't, because there still is no way for the compiler to >> identify >> the container to pass to the Reference aspect. > > You seem to be mixing the particular implementation you would use with > what the standard should allow. There is nothing in the spec of a > reference > type that mandates knowing the container (and the way it currently is done > in the implementations is to use a 'Unrestricted_Access, which is ugly to > say the least). Huh? You are suggesting an alternative description for the existing iterators for the existing containers. (If you're suggesting anything else, you're wasting everybodies time, 'cause something that won't work with the existing containers is a non-starter.) And the Reference function in the existing containers (and in any container I can imagine) takes a container parameter. That parameter has to come from somewhere, and it can't come from the iterator interface (it doesn't include a container in the description). So where does it come from?? Since 'Unrestricted_Access is GNAT junk, it's doesn't have any value for a sample implementation (if you really need 'Unrestricted_Access, then the interface can't be implemented in Ada, and that would be a major problem.) So far as I know, you might need to use 'Unchecked_Access, but that's necessary anytime one needs to get a pointer to save the evaluated version of something. ('Access being useless for 98% of uses; I've only once in my entire programming career been able to use 'Access rather than 'Unchecked_Access). >> If you mean to magically extract it from the call to Depth_First_Search, >> I >> would be strongly against as there is no need for an actual container >> object >> for an iterator (and the model specifically was designed to allow that >> possibility). It would be *much* more limiting to assume a container. > > If I want my iterator to implement depth_first_search, it would indeed > need to > know the container (like most iterators would need to know the container, > in fact). The reference type itself (the end product of the iteration) > doesn't > need to know that though. The container is necessary for the iteration or > traversal of itself, but certainly not once you manipulate an element. You're speaking nonsense. The element is part of the container, and the only way to access it is from the container. You can't create a reference to an element of a container without having the container. But your proposed interface does not have the container anywhere. How does the reference get created??? > My example assumed nothing. Your example is nonsense, IMHO. > The implementation you seem to have in your head seems indeed to assume > a lot of unnecessary things. ??? I'm mapping iteration onto the existing containers. That is straightforward with the existing description, but it's not possible with your proposed redefinition without some modifications. The current definition has a very specific expansion of shorthands into other, existing features. But that's not possible with your proposal. You seem to be expecting magic rather than explaining how to get from A to B, and that's not a possibility with the language standard. >> Definitely a lot more complicated than what we have (and what we have is >> too >> complicated). > > What we have is both too complicated and too limited. Too complicated > because > nobody that hasn't spent a full week will be able to explain how the > aspects > combine with iterators to end up with cursors and the for-of loop. They > just > happen to work for existing containers, but as this thread has proven, > anyone > who tries to actually implement them for other uses that the few official > containers quickly hits sever limitations. The limitations aren't that severe, and seem mostly to be related to having the iterator object be an "in" parameter. (That's probably happened because "in out" parameters on functions seem weird, but they clearly make more sense in this case.) >> > for E of G.Breadth_First_Search loop -- breadth first search, get >> > element >> > null; >> > end loop; >> >> Again, how does the compiler know that G is the container in this >> iterator? >> "G.Breadth_First_Search" is just a function call. On top of which, you >> now >> have two different and unrelated expected types for the iterator, which >> would be a new concept in Ada. > > It is a function call that returns the iterator. So obviously it is > allowed to have > a relationship between the return value and the parameters. The iterator > is therefore allowed (but not mandated, that would depend on the actual > container we are talking about) to have a reference to the container. > This is called flexibility. Something lacking in the current standard. So the iterator has a reference to the container. How would it be used (references being something not related to iterators)? We certainly don't want to be introducing special reference routines *just* for iterators (that's the sort of extra complexity that would have never flown). As for "flexibility", there is plenty; people just seem to have a lack of imagination about this interface (see my replies to Dmitry). I agree that it would have been better if the iterator parameters had been "in out", but that's about it. You're imagining "sever" problems -- Brad had pretty good results with the ACATS test and with the directory iterators. These things aren't expected to be easy to write -- hardly anyone should be doing that anyway (much like generics) -- ease of use is paramount. > I do not understand your last sentence about the two unexpected types. "for E of G loop" -- The expected type is a container with a Default_Iterator aspect. "for E of G.Breadth_First_Search loop" -- The expected type is an iterator with a Default_Iterator aspect. This is two different, unrelated expected types. One could solve that by making this context an "any type" context, and making the checking into Legality Rules, but that means that some expressions would not be allowed ("any type" contexts having restrictions beyond those of other contexts). One could have not allowed the first form, but since that is the only thing people seemed to be asking for, I think that would have been a non-starter. We discussed the question of whether we needed multiple iterators for the "of" form, and the decision was that it was a special shorthand for which additional flexibility -- meaning additional text to write -- would be detremental. I doubt very much that we ever would have allowed multiple expected types - that's evil wherever it appears. >> Making a language "more expressive" is code for "easier to write", which >> never was a goal of Ada. > > That's one of the issue here. The goal for Ada, as I understand it, has > always > been to be "easier to read". There is no reason why "easier to write" > should > be in opposition to that goal. "Easier to write" almost always is in opposition, because it means using shorthands that cannot easily be deciphered by a human. The "for E of Container loop" is certainly in that category, we only allow it because no one other than implementers need to understand how it works in detail. The way one expects it to work is in fact how it works when read - but if you need to understand the details, it's a disaster. >> > I like to clearly >> > state what I mean in the code, but on the other hand why should I have >> > to specify "Element (C)" when I can just use "E" ? >> >> Readability, of course. I don't believe that you should ever have been >> allowed to just specify E. I lost that argument 'cause it wasn't >> sufficiently evil to waste scarce political capital on, but I don't see >> any > > Now I understand. You are re-fighting a fight you lost apparently. But > from > talking to all my colleagues (all of whom are of course Ada experts), we > all > much prefer the form with just "E" in practice. So that change was a great > improvement in the standard, if not quite wide reaching enough. I'm not "refighting" it; you're saying that some nonsense that won't even work is some sort of improvement when it actually would harm understandability of the text. That's an expansion of the functionality, and I'm definitely against any expansion of this idea. One reason is that Ada is gaining too many nice-to-have bells and whistles, to the point that we're losing implementations (after all, there are no Ada 2012 implementations other than GNAT). We can't keep adding cruft, especially when important stuff (parallel operations, for instance) need addressing. Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-16 19:13 ` Randy Brukardt @ 2015-11-16 20:47 ` Dmitry A. Kazakov 2015-11-17 21:30 ` Randy Brukardt 2015-11-16 21:50 ` Simon Wright 2015-11-17 8:49 ` briot.emmanuel 2 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-16 20:47 UTC (permalink / raw) On Mon, 16 Nov 2015 13:13:05 -0600, Randy Brukardt wrote: > You're speaking nonsense. The element is part of the container, and the only > way to access it is from the container. I think you are confusing indices with iterators. The very concept of the iterator is accessing elements without the container as opposed to the index. > You can't create a reference to an > element of a container without having the container. But your proposed > interface does not have the container anywhere. How does the reference get > created??? From the old reference of course. Iterators are pointers. Both concepts of iterator and index have fundamental operations to create a new instance referencing some other element (next, previous, sibling, parent, neighbour etc) >>> Making a language "more expressive" is code for "easier to write", which >>> never was a goal of Ada. >> >> That's one of the issue here. The goal for Ada, as I understand it, has always >> been to be "easier to read". There is no reason why "easier to write" should >> be in opposition to that goal. > > "Easier to write" almost always is in opposition, because it means using > shorthands that cannot easily be deciphered by a human. The "for E of > Container loop" is certainly in that category, we only allow it because no > one other than implementers need to understand how it works in detail. The > way one expects it to work is in fact how it works when read - but if you > need to understand the details, it's a disaster. A disaster is when nobody can understand the details. The concept of iteration is simple, so an implementation of its syntax sugar (nothing more than sugar) must be easily readable and writeable, since all work is already done in the container. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-16 20:47 ` Dmitry A. Kazakov @ 2015-11-17 21:30 ` Randy Brukardt 2015-11-18 9:53 ` Dmitry A. Kazakov 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-17 21:30 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:8hw612c7lfik.1cy0uanjjnpzv$.dlg@40tude.net... > On Mon, 16 Nov 2015 13:13:05 -0600, Randy Brukardt wrote: > >> You're speaking nonsense. The element is part of the container, and the >> only >> way to access it is from the container. > > I think you are confusing indices with iterators. The very concept of the > iterator is accessing elements without the container as opposed to the > index. That's surely not my idea of an iterator. And it doesn't work for Ada in any case, as that would allow altering elements of constant containers (we prevent that in the containers library by requiring an "in out" container parameter in all cases where modifications are allowed). >> You can't create a reference to an >> element of a container without having the container. But your proposed >> interface does not have the container anywhere. How does the reference >> get >> created??? > > From the old reference of course. Iterators are pointers. Nonsense. > Both concepts of > iterator and index have fundamental operations to create a new instance > referencing some other element (next, previous, sibling, parent, neighbour > etc) The C++ containers mix up the ideas of iterators and cursors (they're essentially the same thing there). By your description, you want them to be the same -- but in that case, just use the cursors and be done with it. You will sacrifice safety and ease-of-use to do so, but whatever. >>>> Making a language "more expressive" is code for "easier to write", >>>> which >>>> never was a goal of Ada. >>> >>> That's one of the issue here. The goal for Ada, as I understand it, has >>> always >>> been to be "easier to read". There is no reason why "easier to write" >>> should >>> be in opposition to that goal. >> >> "Easier to write" almost always is in opposition, because it means using >> shorthands that cannot easily be deciphered by a human. The "for E of >> Container loop" is certainly in that category, we only allow it because >> no >> one other than implementers need to understand how it works in detail. >> The >> way one expects it to work is in fact how it works when read - but if you >> need to understand the details, it's a disaster. > > A disaster is when nobody can understand the details. The concept of > iteration is simple, so an implementation of its syntax sugar (nothing > more > than sugar) must be easily readable and writeable, since all work is > already done in the container. Well, that's what we did, but you don't seem to be able to see it. Can't help with that... Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-17 21:30 ` Randy Brukardt @ 2015-11-18 9:53 ` Dmitry A. Kazakov 2015-11-18 22:27 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-18 9:53 UTC (permalink / raw) On Tue, 17 Nov 2015 15:30:28 -0600, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:8hw612c7lfik.1cy0uanjjnpzv$.dlg@40tude.net... >> On Mon, 16 Nov 2015 13:13:05 -0600, Randy Brukardt wrote: >> >>> You're speaking nonsense. The element is part of the container, and the >>> only way to access it is from the container. >> >> I think you are confusing indices with iterators. The very concept of the >> iterator is accessing elements without the container as opposed to the >> index. > > That's surely not my idea of an iterator. And it doesn't work for Ada in any > case, as that would allow altering elements of constant containers (we > prevent that in the containers library by requiring an "in out" container > parameter in all cases where modifications are allowed). Access /= Update. Compare it with "access constant T" The difference between index and iterator is that accessing through the index requires the container. An index is always relative to some container. The iterator does not need the container, the container is implicit. >> Both concepts of >> iterator and index have fundamental operations to create a new instance >> referencing some other element (next, previous, sibling, parent, neighbour >> etc) > > The C++ containers mix up the ideas of iterators and cursors (they're > essentially the same thing there). By your description, you want them to be > the same -- but in that case, just use the cursors and be done with it. You > will sacrifice safety and ease-of-use to do so, but whatever. That is not my point. It is that Index + 1 is another index and that Iterator.Next is another iterator. From the interface point of view you don't need the container to get another instance of either. And regarding safety, it is very important that you don't need the container when accessing elements or advancing the iterator. Well-designed iterators meant to keep the iteration state *inside* the iterator object rather than in the container, for evident reasons. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-18 9:53 ` Dmitry A. Kazakov @ 2015-11-18 22:27 ` Randy Brukardt 2015-11-19 8:52 ` Dmitry A. Kazakov 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-18 22:27 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:ojkj222dh308.y5p6iz7kqgjc.dlg@40tude.net... > On Tue, 17 Nov 2015 15:30:28 -0600, Randy Brukardt wrote: > >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> news:8hw612c7lfik.1cy0uanjjnpzv$.dlg@40tude.net... >>> On Mon, 16 Nov 2015 13:13:05 -0600, Randy Brukardt wrote: >>> >>>> You're speaking nonsense. The element is part of the container, and the >>>> only way to access it is from the container. >>> >>> I think you are confusing indices with iterators. The very concept of >>> the >>> iterator is accessing elements without the container as opposed to the >>> index. >> >> That's surely not my idea of an iterator. And it doesn't work for Ada in >> any >> case, as that would allow altering elements of constant containers (we >> prevent that in the containers library by requiring an "in out" container >> parameter in all cases where modifications are allowed). > > Access /= Update. Compare it with "access constant T" True, but irrelevant. Iterators without update compatibilities are way to limiting to be of any value. > The difference between index and iterator is that accessing through the > index requires the container. An index is always relative to some > container. The iterator does not need the container, the container is > implicit. This is the confusion between "iterators" and "cursors" that the C++ libraries have. What you are describing as an "iterator" is exactly the definition of a cursor in Ada. To me, iterators are active objects, not just indexes. >>> Both concepts of >>> iterator and index have fundamental operations to create a new instance >>> referencing some other element (next, previous, sibling, parent, >>> neighbour >>> etc) >> >> The C++ containers mix up the ideas of iterators and cursors (they're >> essentially the same thing there). By your description, you want them to >> be >> the same -- but in that case, just use the cursors and be done with it. >> You >> will sacrifice safety and ease-of-use to do so, but whatever. > > That is not my point. It is that Index + 1 is another index and that > Iterator.Next is another iterator. From the interface point of view you > don't need the container to get another instance of either. Next(Cursor) gets you another Cursor. (You can't use the prefix notation because Cursors aren't tagged, and that's because we can't have primitive operations of two tagged types, else they would have been tagged. But otherwise this is identical.) You don't need the container to call Next. But you do need the container to update the element. > And regarding safety, it is very important that you don't need the > container when accessing elements or advancing the iterator. Well-designed > iterators meant to keep the iteration state *inside* the iterator object > rather than in the container, for evident reasons. ??? If the container (not counting the contents of the elements) is modified while the iterator is executing, it doesn't matter where the iteration is happening -- you're not going to be able to maintain the invariants of the execution. That happens with explicit iteration in the Ada.Containers (that is, directly using Next and Cursors) -- where the effect is for the user to figure out (and it's often erroneous) -- and that happens with any possible iterator mechanism (using call-backs, or interfaces, or whatever) -- where Ada uses a tampering check to avoid problems (the container does not allow element insertions or deletions while an iteration is running). If you think allowing erroneous execution is somehow safe, you're in the wrong language forum. Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-18 22:27 ` Randy Brukardt @ 2015-11-19 8:52 ` Dmitry A. Kazakov 2015-11-19 21:15 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: Dmitry A. Kazakov @ 2015-11-19 8:52 UTC (permalink / raw) On Wed, 18 Nov 2015 16:27:31 -0600, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:ojkj222dh308.y5p6iz7kqgjc.dlg@40tude.net... >> On Tue, 17 Nov 2015 15:30:28 -0600, Randy Brukardt wrote: >> >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >>> news:8hw612c7lfik.1cy0uanjjnpzv$.dlg@40tude.net... >>>> On Mon, 16 Nov 2015 13:13:05 -0600, Randy Brukardt wrote: >>>> >>>>> You're speaking nonsense. The element is part of the container, and the >>>>> only way to access it is from the container. >>>> >>>> I think you are confusing indices with iterators. The very concept of the >>>> iterator is accessing elements without the container as opposed to the >>>> index. >>> >>> That's surely not my idea of an iterator. And it doesn't work for Ada in any >>> case, as that would allow altering elements of constant containers (we >>> prevent that in the containers library by requiring an "in out" container >>> parameter in all cases where modifications are allowed). >> >> Access /= Update. Compare it with "access constant T" > > True, but irrelevant. Iterators without update compatibilities are way to > limiting to be of any value. I was answering your point. Clearly iterators, as pointers are, can be immutable themselves and/or refer to the immutable target. If container is immutable you should not be able to obtain a mutable-target iterator from it. Where is a problem? >> The difference between index and iterator is that accessing through the >> index requires the container. An index is always relative to some >> container. The iterator does not need the container, the container is >> implicit. > > This is the confusion between "iterators" and "cursors" that the C++ > libraries have. What you are describing as an "iterator" is exactly the > definition of a cursor in Ada. To me, iterators are active objects, not just > indexes. Iterator is not an index, I explained the difference. Index needs explicit container in the indexing operation. Iterator/cursor is nothing but a fat pointer. Pointers do not need explicit container (=memory pool) for dereferencing. This has nothing to do with specifically C++. E.g. DB interfaces have "cursors", GUI frameworks have "iterators" etc. The semantics of such object is same: Cursor = Iterator = Pointer >>>> Both concepts of >>>> iterator and index have fundamental operations to create a new instance >>>> referencing some other element (next, previous, sibling, parent, >>>> neighbour etc) >>> >>> The C++ containers mix up the ideas of iterators and cursors (they're >>> essentially the same thing there). By your description, you want them to >>> be the same -- but in that case, just use the cursors and be done with it. >>> You will sacrifice safety and ease-of-use to do so, but whatever. >> >> That is not my point. It is that Index + 1 is another index and that >> Iterator.Next is another iterator. From the interface point of view you >> don't need the container to get another instance of either. > > Next(Cursor) gets you another Cursor. (You can't use the prefix notation > because Cursors aren't tagged, and that's because we can't have primitive > operations of two tagged types, else they would have been tagged. But > otherwise this is identical.) You don't need the container to call Next. But > you do need the container to update the element. Both are just design bugs resulted due to language deficiencies. Clearly, there is no reason why postfix notation should not be allowed for the iterator objects, why the iterator type cannot be inherited from, why container is needed to update its element. As I said many times, fix the language type system first, then design standard containers. In that order. >> And regarding safety, it is very important that you don't need the >> container when accessing elements or advancing the iterator. Well-designed >> iterators meant to keep the iteration state *inside* the iterator object >> rather than in the container, for evident reasons. > > ??? > > If the container (not counting the contents of the elements) is modified > while the iterator is executing, it doesn't matter where the iteration is > happening -- you're not going to be able to maintain the invariants of the > execution. This is an aliasing problem, not a problem of iterator objects, though all iterators always have aliasing issues because of their referential semantics. BTW, speaking of inventing definitions, "iterator" is an object. It is not a process, the latter is called "iteration", "traversing", "search", "walkthrough", "enumeration" etc. > That happens with explicit iteration in the Ada.Containers (that is, > directly using Next and Cursors) -- where the effect is for the user to > figure out (and it's often erroneous) -- and that happens with any possible > iterator mechanism (using call-backs, or interfaces, or whatever) -- where > Ada uses a tampering check to avoid problems (the container does not allow > element insertions or deletions while an iteration is running). Yes, this is one of the worst form of enumeration because it is recursive, hello FP. Should be avoided where possible. > If you think allowing erroneous execution is somehow safe, you're in the > wrong language forum. The point was that keeping the iteration state in the container is more erroneous that keeping it outside in the iterator object. E.g. some implementations store last found element, deploy caching and book-keeping things in the container. That far less safe than keeping that stuff outside the container, e.g. in the iterator object. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-19 8:52 ` Dmitry A. Kazakov @ 2015-11-19 21:15 ` Randy Brukardt 0 siblings, 0 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-19 21:15 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:1wew1bio4hygc.xotxd22aq47g.dlg@40tude.net... > On Wed, 18 Nov 2015 16:27:31 -0600, Randy Brukardt wrote: ... >> If you think allowing erroneous execution is somehow safe, you're in the >> wrong language forum. > > The point was that keeping the iteration state in the container is more > erroneous that keeping it outside in the iterator object. E.g. some > implementations store last found element, deploy caching and book-keeping > things in the container. That far less safe than keeping that stuff > outside > the container, e.g. in the iterator object. Sorry, missed your point originally. I don't think it's possible (in general) to keep the iteration information within the container, as that would mean that you could only do one iteration at a time. Which would be a nasty abstraction break (inner iterations on the same container would have to fail in that case, but for no good reason). That is, if the iterator info is part of the container, then for E of C loop for F of C loop ... end loop; end loop; cannot work. (The inner loop often occurs in some routine called from the body of the loop, it wouldn't be obvious like this is.) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-16 19:13 ` Randy Brukardt 2015-11-16 20:47 ` Dmitry A. Kazakov @ 2015-11-16 21:50 ` Simon Wright 2015-11-17 21:33 ` Randy Brukardt 2015-11-17 8:49 ` briot.emmanuel 2 siblings, 1 reply; 73+ messages in thread From: Simon Wright @ 2015-11-16 21:50 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > Since 'Unrestricted_Access is GNAT junk, it's doesn't have any value > for a sample implementation (if you really need 'Unrestricted_Access, > then the interface can't be implemented in Ada, and that would be a > major problem.) So far as I know, you might need to use > 'Unchecked_Access, but that's necessary anytime one needs to get a > pointer to save the evaluated version of something. I can't of course speak for AdaCore, but I think that the problem is to do with obtaining a writable view of an in parameter; for example, in the Bounded Hashed Map (GCC 5) there is function Iterate (Container : Map) return Map_Iterator_Interfaces.Forward_Iterator'Class is B : Natural renames Container'Unrestricted_Access.all.Busy; begin return It : constant Iterator := (Limited_Controlled with Container => Container'Unrestricted_Access) do B := B + 1; end return; end Iterate; I dare say something could be done with 'Address and Address To Access Conversions. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-16 21:50 ` Simon Wright @ 2015-11-17 21:33 ` Randy Brukardt 2015-11-17 23:14 ` Simon Wright 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-17 21:33 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:ly1tbpipgd.fsf@pushface.org... > "Randy Brukardt" <randy@rrsoftware.com> writes: > >> Since 'Unrestricted_Access is GNAT junk, it's doesn't have any value >> for a sample implementation (if you really need 'Unrestricted_Access, >> then the interface can't be implemented in Ada, and that would be a >> major problem.) So far as I know, you might need to use >> 'Unchecked_Access, but that's necessary anytime one needs to get a >> pointer to save the evaluated version of something. > > I can't of course speak for AdaCore, but I think that the problem is > to do with obtaining a writable view of an in parameter; for example, in > the Bounded Hashed Map (GCC 5) there is > > function Iterate > (Container : Map) return > Map_Iterator_Interfaces.Forward_Iterator'Class > is > B : Natural renames Container'Unrestricted_Access.all.Busy; > begin > return It : constant Iterator := > (Limited_Controlled with > Container => Container'Unrestricted_Access) > do > B := B + 1; > end return; > end Iterate; > > I dare say something could be done with 'Address and Address To Access > Conversions. As Brad noted, you have to use the Rosen technique here. Not hacks like 'Unrestricted_Access. (The Rosen technique is not a "trick", it's an intended part of the language in Ada 2012. I admit it originally was accidental, but it's too widely used to eliminate.) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-17 21:33 ` Randy Brukardt @ 2015-11-17 23:14 ` Simon Wright 0 siblings, 0 replies; 73+ messages in thread From: Simon Wright @ 2015-11-17 23:14 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Simon Wright" <simon@pushface.org> wrote in message > news:ly1tbpipgd.fsf@pushface.org... >> I can't of course speak for AdaCore, but I think that the problem is >> to do with obtaining a writable view of an in parameter; for example, in >> the Bounded Hashed Map (GCC 5) there is >> >> function Iterate >> (Container : Map) return >> Map_Iterator_Interfaces.Forward_Iterator'Class >> is >> B : Natural renames Container'Unrestricted_Access.all.Busy; > As Brad noted, you have to use the Rosen technique here. Not hacks > like 'Unrestricted_Access. (The Rosen technique is not a "trick", it's > an intended part of the language in Ada 2012. I admit it originally > was accidental, but it's too widely used to eliminate.) Does that now work for non-limited types? The anti-tampering bits have to be in the container ... how have other vendors managed this? Brad was talking about using this technique in the iterator. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-16 19:13 ` Randy Brukardt 2015-11-16 20:47 ` Dmitry A. Kazakov 2015-11-16 21:50 ` Simon Wright @ 2015-11-17 8:49 ` briot.emmanuel 2015-11-17 22:09 ` Randy Brukardt 2 siblings, 1 reply; 73+ messages in thread From: briot.emmanuel @ 2015-11-17 8:49 UTC (permalink / raw) > Huh? You are suggesting an alternative description for the existing > iterators for the existing containers. (If you're suggesting anything else, > you're wasting everybodies time, 'cause something that won't work with the > existing containers is a non-starter.) I am trying to think of things should have been done, so that perhaps we can find a way to fix them in future versions of the language. As this discussion as shown, there are lots of very knowledgeable people who are having difficulties with the current design and its limitations. If you think this is wasting your time, by all means feel free to ignore this thread. I have found it pretty interesting so far. > And the Reference function in the > existing containers (and in any container I can imagine) takes a container > parameter. That parameter has to come from somewhere, and it can't come from > the iterator interface (it doesn't include a container in the description). > So where does it come from?? I was talking of the Reference_Type (which doesn't need a container in the public spec, although it is convenient sometimes to have one to ensure the lifetime of the container is greater than that of the reference -- with all the additional performance costs). The Iterator interface is an interface, so of course it doesn't contain anything. An actual Iterator implementation is free to store a reference to the container if it needs it to implement complex algorithms. An iterator could return a reference by building it directly, it doesn't need to go through the Reference function for this. > You're speaking nonsense. The element is part of the container, and the only > way to access it is from the container. You can't create a reference to an > element of a container without having the container. But your proposed > interface does not have the container anywhere. How does the reference get > created??? I'll forward you to the discussion you are having with Dmitry. Your notion of Index vs Cursor vs Iterators seems to be wrong. > I'm mapping iteration onto the existing containers. That is straightforward > with the existing description, No it is not. Anyone who has already tried to implement their own iterators has failed the first time (at AdaCore, but also Simon Wright in the initial message here, at courses we have given in various places,....) > The limitations aren't that severe, and seem mostly to be related to having > the iterator object be an "in" parameter. (That's probably happened because > "in out" parameters on functions seem weird, but they clearly make more > sense in this case.) I'll stop this discussion which indeed is leading nowhere. You started by saying that for-of is useless, so all the rest is moot from your point of view. I can understand where you are coming from. You can't understand where we want to go. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-17 8:49 ` briot.emmanuel @ 2015-11-17 22:09 ` Randy Brukardt 0 siblings, 0 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-17 22:09 UTC (permalink / raw) <briot.emmanuel@gmail.com> wrote in message news:64a2a1bd-7519-4d66-bfb6-9b2a1fb1773b@googlegroups.com... >> Huh? You are suggesting an alternative description for the existing >> iterators for the existing containers. (If you're suggesting anything >> else, >> you're wasting everybodies time, 'cause something that won't work with >> the >> existing containers is a non-starter.) > > I am trying to think of things should have been done, so that perhaps we > can find a > way to fix them in future versions of the language. As this discussion as > shown, there > are lots of very knowledgeable people who are having difficulties with the > current > design and its limitations. If you think this is wasting your time, by all > means feel free > to ignore this thread. I have found it pretty interesting so far. I haven't been ignoring this thread, although I probably should have rather than feeding the trolls. > "there are lots of very knowledgeable people" When it comes to Ada, there are very few knowledgeable people (sadly), so any statement starting with "lots of knowledgeable people" is junk on its face. The only real issue that I've heard from a knowledgeable person is the parameter mode issue (which is always an issue with OOP and Ada, it's not unique here), and there is a very standard approach to mitigate the problem (the Rosen technique). Everything else seems to come from people who want to do C++ or some other language-de-jure in Ada, and that sort of thing has almost always led to making Ada more complex without adding anything of value (anonymous access types, interfaces, etc.) >> And the Reference function in the >> existing containers (and in any container I can imagine) takes a >> container >> parameter. That parameter has to come from somewhere, and it can't come >> from >> the iterator interface (it doesn't include a container in the >> description). >> So where does it come from?? > > I was talking of the Reference_Type (which doesn't need a container in the > public > spec, although it is convenient sometimes to have one to ensure the > lifetime of > the container is greater than that of the reference -- with all the > additional > performance costs). I'm still confused. Where does the value of the Reference_Type come from? It has to come from the call of some function. (More below.) > The Iterator interface is an interface, so of course it doesn't contain > anything. An > actual Iterator implementation is free to store a reference to the > container if it needs > it to implement complex algorithms. An iterator could return a reference > by building > it directly, it doesn't need to go through the Reference function for > this. Building it directly from what? An iterator (in Ada today) is an interface of functions that are called to implement the iteration syntax. Are you proposing to scrap that model? If so, then you have to explain how an iterator type maps to iteration syntax. If not, then you have to describe the functions called and where in that syntax. One way to do that latter would be to create additional iterator interfaces. *That* would work, rather than additional aspects that don't connect to anything. In that case, the function that created the reference type would take a value of the iterator object. That could look something like (names would of course be TBD, "EB" is in honor of you, of course): generic type Cursor; with function Has_Element (Position : Cursor) return Boolean; type Reference_Type is private; package Ada.EB_Iterator_Interfaces is pragma Pure (Iterator_Interfaces); package II is new Ada.Iterator_Interfaces (Cursor, Has_Element); type EB_Forward_Iterator is limited new II.Forward_Iterator with null record; function First (Object : Forward_Iterator) return Cursor is abstract; function Next (Object : Forward_Iterator; Position : Cursor) return Cursor is abstract; function Reference (Object : Forward_Iterator; Position : Cursor) return Reference_Type is abstract; -- Similarly for Reverse_Iterator. end Ada.EB_Iterator_Interfaces; Then one could explain the mapping of iterators to references via calls to Reference, and the relationship with the other iterators. As previously noted, I'm unconvinced this is a good idea, but at least the above would work. Your proposals are leaving out steps that have to be defined in order for it to be a language feature. >> You're speaking nonsense. The element is part of the container, and the >> only >> way to access it is from the container. You can't create a reference to >> an >> element of a container without having the container. But your proposed >> interface does not have the container anywhere. How does the reference >> get >> created??? > > I'll forward you to the discussion you are having with Dmitry. Your notion > of > Index vs Cursor vs Iterators seems to be wrong. No, his notion of index vs. cursor vs. iterators is nonsense. That's typical for him, he uses his own definitions for things, whether or not they have anything to do with the subject at hand. It's something one learns to ignore here (it's pointless to argue with him about it). The only definitions I use are the ones in the Ada Reference Manual. All else is irrelevant to me. >> I'm mapping iteration onto the existing containers. That is >> straightforward >> with the existing description, > > No it is not. Anyone who has already tried to implement their own > iterators > has failed the first time (at AdaCore, but also Simon Wright in the > initial > message here, at courses we have given in various places,....) That's the effect of the lack of good examples more than any problem with the interface. Brad's ACATS tests provide some good examples for users to study, hopefully examples like that will get more play. >> The limitations aren't that severe, and seem mostly to be related to >> having >> the iterator object be an "in" parameter. (That's probably happened >> because >> "in out" parameters on functions seem weird, but they clearly make more >> sense in this case.) > > I'll stop this discussion which indeed is leading nowhere. You started by > saying > that for-of is useless, so all the rest is moot from your point of view. I > can > understand where you are coming from. You can't understand where we want > to go. I think I do understand where you want to go, and I really don't think Ada should be going there. Certainly not for sequential programs (I'm more open to change on the parallel side because what we have is way too hard to use). Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-05 1:20 ` Randy Brukardt 2015-11-05 8:34 ` briot.emmanuel @ 2015-11-05 8:45 ` Simon Wright 2015-11-05 8:52 ` Simon Wright 1 sibling, 1 reply; 73+ messages in thread From: Simon Wright @ 2015-11-05 8:45 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > Prime_Number_Set is (directly) an iterator, so you use "in" to iterate > over it: > > for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop > > The "of" form is for iterating over an array or a container whose type > has the Default_Iterator aspect (which gives the iterator to use). > > I can hear the head slap from here. ;-) Yes, but; 1. with Ada.Text_IO; 2. with F552A00_Prime_Numbers; 3. procedure Primes is 4. begin 5. for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop | >>> expected a discrete type >>> found type "Prime_Number_Set" defined at f552a00_prime_numbers.ads:74 6. Ada.Text_IO.Put_Line (P'Img); 7. end loop; 8. end Primes; Perhaps this is the GNAT problem you spoke of? (FSF GCC 5.1.0, GNAT GPL 2015) ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-05 8:45 ` Simon Wright @ 2015-11-05 8:52 ` Simon Wright 2015-11-12 18:29 ` Randy Brukardt 2015-11-12 18:32 ` Randy Brukardt 0 siblings, 2 replies; 73+ messages in thread From: Simon Wright @ 2015-11-05 8:52 UTC (permalink / raw) Simon Wright <simon@pushface.org> writes: > "Randy Brukardt" <randy@rrsoftware.com> writes: > >> Prime_Number_Set is (directly) an iterator, so you use "in" to iterate >> over it: >> >> for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop >> >> The "of" form is for iterating over an array or a container whose type >> has the Default_Iterator aspect (which gives the iterator to use). >> >> I can hear the head slap from here. ;-) > > Yes, but; > > 1. with Ada.Text_IO; > 2. with F552A00_Prime_Numbers; > 3. procedure Primes is > 4. begin > 5. for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop > | > >>> expected a discrete type > >>> found type "Prime_Number_Set" defined at > >>> f552a00_prime_numbers.ads:74 > > 6. Ada.Text_IO.Put_Line (P'Img); > 7. end loop; > 8. end Primes; > > Perhaps this is the GNAT problem you spoke of? (FSF GCC 5.1.0, GNAT GPL 2015) Oh, it should have been for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31).Iterate loop ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-05 8:52 ` Simon Wright @ 2015-11-12 18:29 ` Randy Brukardt 2015-11-12 18:32 ` Randy Brukardt 1 sibling, 0 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-12 18:29 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:lyziyskeu2.fsf@pushface.org... > Simon Wright <simon@pushface.org> writes: > >> "Randy Brukardt" <randy@rrsoftware.com> writes: >> >>> Prime_Number_Set is (directly) an iterator, so you use "in" to iterate >>> over it: >>> >>> for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop >>> >>> The "of" form is for iterating over an array or a container whose type >>> has the Default_Iterator aspect (which gives the iterator to use). >>> >>> I can hear the head slap from here. ;-) >> >> Yes, but; >> >> 1. with Ada.Text_IO; >> 2. with F552A00_Prime_Numbers; >> 3. procedure Primes is >> 4. begin >> 5. for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => >> 31) loop >> | >> >>> expected a discrete type >> >>> found type "Prime_Number_Set" defined at >> >>> f552a00_prime_numbers.ads:74 >> >> 6. Ada.Text_IO.Put_Line (P'Img); >> 7. end loop; >> 8. end Primes; >> >> Perhaps this is the GNAT problem you spoke of? (FSF GCC 5.1.0, GNAT GPL >> 2015) > > Oh, it should have been > > for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => > 31).Iterate > loop Right. You got two head slaps for the price of one. :-) Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-05 8:52 ` Simon Wright 2015-11-12 18:29 ` Randy Brukardt @ 2015-11-12 18:32 ` Randy Brukardt 2015-11-12 20:02 ` Simon Wright 1 sibling, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-12 18:32 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:lyziyskeu2.fsf@pushface.org... > Simon Wright <simon@pushface.org> writes: > >> "Randy Brukardt" <randy@rrsoftware.com> writes: >> >>> Prime_Number_Set is (directly) an iterator, so you use "in" to iterate >>> over it: >>> >>> for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => 31) loop >>> >>> The "of" form is for iterating over an array or a container whose type >>> has the Default_Iterator aspect (which gives the iterator to use). >>> >>> I can hear the head slap from here. ;-) >> >> Yes, but; >> >> 1. with Ada.Text_IO; >> 2. with F552A00_Prime_Numbers; >> 3. procedure Primes is >> 4. begin >> 5. for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => >> 31) loop >> | >> >>> expected a discrete type >> >>> found type "Prime_Number_Set" defined at >> >>> f552a00_prime_numbers.ads:74 >> >> 6. Ada.Text_IO.Put_Line (P'Img); >> 7. end loop; >> 8. end Primes; >> >> Perhaps this is the GNAT problem you spoke of? (FSF GCC 5.1.0, GNAT GPL >> 2015) > > Oh, it should have been > > for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => > 31).Iterate > loop I probably would have made type Prime_Number_Set directly the iterator type (I don't see any other need for it), which would get rid of the need for the ".Iterate". An iterator doesn't necessarily have to have anything to do with a container! Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 18:32 ` Randy Brukardt @ 2015-11-12 20:02 ` Simon Wright 2015-11-12 21:08 ` Randy Brukardt 0 siblings, 1 reply; 73+ messages in thread From: Simon Wright @ 2015-11-12 20:02 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Simon Wright" <simon@pushface.org> wrote in message > news:lyziyskeu2.fsf@pushface.org... >> Oh, it should have been >> >> for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => >> 31).Iterate >> loop > > I probably would have made type Prime_Number_Set directly the iterator > type (I don't see any other need for it), which would get rid of the > need for the ".Iterate". An iterator doesn't necessarily have to have > anything to do with a container! Hmm. A Prime_Number_Set is a new Prime_Number_Iterator.Forward_Iterator; Iterate returns a Prime_Number_Iterator.Forward_Iterator'Class. I tried without the .Iterate, as before, and with for P in Prime_Number_Set'Class (Prime_Number_Set'(Max_Value => 30)) (just in case) and as before got the 'expected a discrete type' error. Perhaps this is a GNAT bug? On the other hand, why did Brad include function Iterate? ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 20:02 ` Simon Wright @ 2015-11-12 21:08 ` Randy Brukardt 2015-11-15 17:56 ` Brad Moore 0 siblings, 1 reply; 73+ messages in thread From: Randy Brukardt @ 2015-11-12 21:08 UTC (permalink / raw) "Simon Wright" <simon@pushface.org> wrote in message news:ly4mgrj8ab.fsf@pushface.org... > "Randy Brukardt" <randy@rrsoftware.com> writes: > >> "Simon Wright" <simon@pushface.org> wrote in message >> news:lyziyskeu2.fsf@pushface.org... > >>> Oh, it should have been >>> >>> for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => >>> 31).Iterate >>> loop >> >> I probably would have made type Prime_Number_Set directly the iterator >> type (I don't see any other need for it), which would get rid of the >> need for the ".Iterate". An iterator doesn't necessarily have to have >> anything to do with a container! > > Hmm. > > A Prime_Number_Set is a new Prime_Number_Iterator.Forward_Iterator; > Iterate returns a Prime_Number_Iterator.Forward_Iterator'Class. > > I tried without the .Iterate, as before, and with > > for P in Prime_Number_Set'Class (Prime_Number_Set'(Max_Value => 30)) > > (just in case) and as before got the 'expected a discrete type' error. It should work either way. But does it work if you write: for P in Prime_Number_Iterator.Forward_Iterator'Class (Prime_Number_Set'(Max_Value => 30)) ?? If so, GNAT surely has a bug (the type conversion shouldn't change anything). You could also try: for P in Prime_Number_Iterator.Forward_Iterator'(Prime_Number_Set'(Max_Value => 30)) which also shouldn't change anything. > Perhaps this is a GNAT bug? Looks like it to me. > On the other hand, why did Brad include function Iterate? It appears that he wanted tracing of the initialization (as that is all it does other than making a new iterator that is a copy of the first). It shouldn't be necessary. Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-12 21:08 ` Randy Brukardt @ 2015-11-15 17:56 ` Brad Moore 2015-11-15 21:42 ` Simon Wright 2015-11-16 19:16 ` Randy Brukardt 0 siblings, 2 replies; 73+ messages in thread From: Brad Moore @ 2015-11-15 17:56 UTC (permalink / raw) On Thursday, November 12, 2015 at 2:08:54 PM UTC-7, Randy Brukardt wrote: > "Simon Wright" <simon@pushface.org> wrote in message > news:ly4mgrj8ab.fsf@pushface.org... > > "Randy Brukardt" <randy@rrsoftware.com> writes: > > > >> "Simon Wright" <simon@pushface.org> wrote in message > >> news:lyziyskeu2.fsf@pushface.org... > > > >>> Oh, it should have been > >>> > >>> for P in F552A00_Prime_Numbers.Prime_Number_Set'(Max_Value => > >>> 31).Iterate > >>> loop > >> > >> I probably would have made type Prime_Number_Set directly the iterator > >> type (I don't see any other need for it), which would get rid of the > >> need for the ".Iterate". An iterator doesn't necessarily have to have > >> anything to do with a container! > > > > Hmm. > > > > A Prime_Number_Set is a new Prime_Number_Iterator.Forward_Iterator; > > Iterate returns a Prime_Number_Iterator.Forward_Iterator'Class. > > > > I tried without the .Iterate, as before, and with > > > > for P in Prime_Number_Set'Class (Prime_Number_Set'(Max_Value => 30)) > > > > (just in case) and as before got the 'expected a discrete type' error. > > It should work either way. But does it work if you write: > > for P in Prime_Number_Iterator.Forward_Iterator'Class > (Prime_Number_Set'(Max_Value => 30)) This doesn't work either > > ?? If so, GNAT surely has a bug (the type conversion shouldn't change > anything). You could also try: > > for P in > Prime_Number_Iterator.Forward_Iterator'(Prime_Number_Set'(Max_Value => 30)) This doesn't work also. However, if I declare the iterator as a declared object as in; Iterator : constant Prime_Number_Iterator.Forward_Iterator'Class := Prime_Number_Set'(Max_Value => 30); Then I can do this; for Prime in Iterator loop Put_Line (Integer'Image (Prime)); end loop; However, if I declare it this way... Iterator : constant Prime_Number_Set := Prime_Number_Set'(Max_Value => 30); Then the loop above does not compile. So it seems to me that there are some GNAT bugs in this area. > > which also shouldn't change anything. > > > Perhaps this is a GNAT bug? > > Looks like it to me. > > > On the other hand, why did Brad include function Iterate? > > It appears that he wanted tracing of the initialization (as that is all it > does other than making a new iterator that is a copy of the first). It > shouldn't be necessary. It's been a while since I wrote that example, and I'm not entirely sure why I did it that way, but to be honest, I think I started with the existing container iterators as my starting point example, which all have an Iterate function, and I may have just assumed I needed a function which returned an class-wide object. If the Prime Number Iterator is useful as an example for others, it would be nice to eliminate the Iterate function from the example. It seems also that there should be some more tests written to cover the failure cases that we are discovering now. I'd be happy to update this ACATS test, if Randy thinks its worthwhile. Brad ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-15 17:56 ` Brad Moore @ 2015-11-15 21:42 ` Simon Wright 2015-11-16 19:16 ` Randy Brukardt 1 sibling, 0 replies; 73+ messages in thread From: Simon Wright @ 2015-11-15 21:42 UTC (permalink / raw) Brad Moore <bmoore.ada@gmail.com> writes: > However, if I declare it this way... > > Iterator : constant Prime_Number_Set := > Prime_Number_Set'(Max_Value => 30); > > Then the loop above does not compile. Indeed, gives a GNAT bug box! (GPL 2015, 5.1.0, 6.0.0 all behave the same) > So it seems to me that there are some GNAT bugs in this area. Yes. I reported it on Saturday .. hoping for a response. ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-11-15 17:56 ` Brad Moore 2015-11-15 21:42 ` Simon Wright @ 2015-11-16 19:16 ` Randy Brukardt 1 sibling, 0 replies; 73+ messages in thread From: Randy Brukardt @ 2015-11-16 19:16 UTC (permalink / raw) "Brad Moore" <bmoore.ada@gmail.com> wrote in message news:68087ee3-fc89-4c13-b5c4-3cd8984e9643@googlegroups.com... On Thursday, November 12, 2015 at 2:08:54 PM UTC-7, Randy Brukardt wrote: ... >> > On the other hand, why did Brad include function Iterate? >> >> It appears that he wanted tracing of the initialization (as that is all >> it >> does other than making a new iterator that is a copy of the first). It >> shouldn't be necessary. > >It's been a while since I wrote that example, and I'm not entirely sure why >I did it >that way, but to be honest, I think I started with the existing container >iterators as >my starting point example, which all have an Iterate function, and I may >have just >assumed I needed a function which returned an class-wide object. >If the Prime Number Iterator is useful as an example for others, it would >be nice to >eliminate the Iterate function from the example. It seems also that there >should be >some more tests written to cover the failure cases that we are discovering >now. I'd >be happy to update this ACATS test, if Randy thinks its worthwhile. I think it would be good to have a separate test using this model (you wouldn't need to change the foundation to do it - I think - you'd just not call the Iterate function). I don't want to change existing ACATS tests unless they are actually wrong (and none of these are). Randy. ^ permalink raw reply [flat|nested] 73+ messages in thread
* A few questions @ 2015-02-07 17:43 Laurent 2015-02-07 22:15 ` Brad Moore 0 siblings, 1 reply; 73+ messages in thread From: Laurent @ 2015-02-07 17:43 UTC (permalink / raw) Hi 1) Trying to implement a search function in my linked list. Doesn't compile because the return type :List_Ptr is not visible in the ads file? spec: function Search (L : in List; Element : in Element_Type) return List_Ptr; -- Pre: L is defined; L may be empty; Element is a scalar type -- Post: returns access to found node body function Search (L : in List; Element : in Element_Type) return List_Ptr is Temp : List_Ptr; Current : List; begin Current := L.Head; while Current.Head /= null loop if Equals(Current.Head.Element, Element) then Temp:= Current.Head; return Temp; end if; Current.Head := Current.Head.Next; end loop; end Search; The List_Ptr is defined as: private ---------- -- List -- ---------- type List_Node; type List_Ptr is access List_Node; type List_Node is record Element : Element_Type; Next : List_Ptr; Previous:List_Ptr; end record; type List is record Head : List_Ptr; Tail : List_Ptr; end record; I have put the search function in a child package. 2) Tried the same thing but this time using an iterator but fails with 65:20 (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2)) 65:20 return by reference not permitted in Ada 2005 on return It; spec function Search (L : access List; Element : Element_Type) return Iterator; -- Pre: L is defined; L may be empty; Element is a scalar type -- Post: returns access to found node body function Search (L : access List; Element : Element_Type) return Iterator is It : Iterator (L); begin Start (It); while not Done (It) loop if Equals (It.This.Element, Element) then return It; end if; Next(It); end loop; end Search; The Iterator is defined as: private -------------- -- Iterator -- -------------- type Iterator (L : access List) is limited record This : List_Ptr; end record; I have tried to understand RM-2005 6.5(5.5/2) but don't know what "If the result subtype of the function is defined by a subtype_mark, the return_subtype_indication shall be a subtype_indication. The type of the subtype_indication shall be the result type of the function" is supposed to look like. If someone could enlighten me on both problems. https://github.com/Chutulu/Chapter-15.git 3) How can I take a look at the assembler code of both versions? Just curious to see if there is actually a difference between both versions. I have no idea of assembler but that doesn't keep me from trying. Thanks Laurent ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-02-07 17:43 Laurent @ 2015-02-07 22:15 ` Brad Moore 2015-02-08 22:37 ` Laurent 0 siblings, 1 reply; 73+ messages in thread From: Brad Moore @ 2015-02-07 22:15 UTC (permalink / raw) On 15-02-07 10:43 AM, Laurent wrote: > Hi > > 1) Trying to implement a search function in my linked list. Doesn't compile because the return type :List_Ptr is not visible in the ads file? The compiler is telling you that List_Ptr can't be used in the visible part of a package (the part before the word private), if it hasn't been defined yet. (ie the definition is not seen until further down in the file inside the private part of the package. Your abstraction in this case involves the use of something called List_Ptr, and users of your abstraction should be able to use your package without having to look inside the private part of the package. One way to get around this, is to define List_Ptr as a private type in the visible part of the package. eg. type List_Ptr is private; The full definition of List_Ptr still occurs in the private part of the package as you have it, but the private type declaration in the visible part of the package exposes the name of the type in the visible part so that it can be used there. > > spec: > > function Search (L : in List; Element : in Element_Type) return List_Ptr; > -- Pre: L is defined; L may be empty; Element is a scalar type > -- Post: returns access to found node > > body > > function Search (L : in List; Element : in Element_Type) return List_Ptr is > Temp : List_Ptr; > Current : List; > > begin > Current := L.Head; > while Current.Head /= null loop > if Equals(Current.Head.Element, Element) then > Temp:= Current.Head; > return Temp; > end if; > Current.Head := Current.Head.Next; > end loop; > end Search; > > The List_Ptr is defined as: > > private > > ---------- > -- List -- > ---------- > > type List_Node; > type List_Ptr is access List_Node; > type List_Node is record > Element : Element_Type; > Next : List_Ptr; > Previous:List_Ptr; > end record; > > type List is record > Head : List_Ptr; > Tail : List_Ptr; > end record; > > I have put the search function in a child package. A child package isn't necessary for this purpose. > > 2) Tried the same thing but this time using an iterator but fails with > > 65:20 (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2)) The compiler is complaining because you have declared It as a local object inside your Search function, and you are trying to return that object as the result of a function call, which involves copying the object to wherever the result of the function call is to be placed. Limited types are not copyable. Is there a reason why you declared your Iterator type to be a limited type, (ie. with the keyword limited)? If you do want it to be a limited type you can return an object of that type in a function call in certain contexts. You have to use an extended return statement though. See RM 6.5 (2.1/2) and 6.5 (28/2) for an example. That would allow the return object to be built in place where the function result is to be placed, and thus avoids copying any object. Such a function that returns a limited type is usable only to initialize a declaration of a limited type. You cannot use it to change the value of the limited type once it has been initialized. This may be too restrictive for your needs, so perhaps you should consider not making this type limited. > 65:20 return by reference not permitted in Ada 2005 > on > > return It; > > spec > > function Search (L : access List; Element : Element_Type) return Iterator; > -- Pre: L is defined; L may be empty; Element is a scalar type > -- Post: returns access to found node > > body > > function Search (L : access List; Element : Element_Type) return Iterator is > It : Iterator (L); > > begin > Start (It); > while not Done (It) loop > if Equals (It.This.Element, Element) then > return It; > end if; > Next(It); > end loop; > end Search; > > The Iterator is defined as: > > private > > -------------- > -- Iterator -- > -------------- > > type Iterator (L : access List) is limited > record > This : List_Ptr; > end record; > > I have tried to understand RM-2005 6.5(5.5/2) but don't know what > > "If the result subtype of the function is defined by a subtype_mark, the return_subtype_indication shall be a subtype_indication. The type of the subtype_indication shall be the result type of the function" > > is supposed to look like. I believe you are referring to 6.5(5.2/2) not 6.5(5.5/2) This applies to an extended return statement. In your example, you are using a simple return statement, if you want to use an extended return, you need to use that syntax. The result subtype of your function is defined by a subtype_mark (Iterator), so 6.5(5.2/2) is saying that the declaration of the result object in the extended return must also be an Iterator, but you may optionally add further constraints on the declaration. In your case, you need to add a discriminant constraint for the access to the List discriminant, since you want the result to have that value. eg. return Result (L) : Iterator do null; end return; Brad > > If someone could enlighten me on both problems. > > https://github.com/Chutulu/Chapter-15.git > > 3) How can I take a look at the assembler code of both versions? Just curious to see if there is actually a difference between both versions. I have no idea of assembler but that doesn't keep me from trying. > > Thanks > > Laurent > ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-02-07 22:15 ` Brad Moore @ 2015-02-08 22:37 ` Laurent 2015-02-09 13:56 ` Brad Moore 0 siblings, 1 reply; 73+ messages in thread From: Laurent @ 2015-02-08 22:37 UTC (permalink / raw) On Saturday, February 7, 2015 at 11:14:46 PM UTC+1, Brad Moore wrote: > One way to get around this, is to define List_Ptr as a private type in > the visible part of the package. > > eg. > > type List_Ptr is private; Ok that makes sense. As the package is based on an example from my Ada95 book, only the List type is visible. But the author had probably a good reason to design it like this? > A child package isn't necessary for this purpose. Has to do with the fact that the "Insert_In_Order" procedure requires overriding of >= and <, if Element_Type is a record... So a child package makes things easier if I don't need this procedure. Same is true for the search function which requires an overridden =. So I put it in the child package. > > 65:20 (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2)) Oops wrong paragraphe, indeed meant 6.5(5.5/2) copied the wrong one > The compiler is complaining because you have declared It as a local > object inside your Search function, and you are trying to return that > object as the result of a function call, which involves copying the > object to wherever the result of the function call is to be placed. > > Limited types are not copyable. Is there a reason why you declared your > Iterator type to be a limited type, (ie. with the keyword limited)? No idea why it is limited. Took the example of the active iterator from John Barnes Ada 2005 book. But again I suppose that the author had a good reason to make the Iterator limited? > If you do want it to be a limited type you can return an object of that > type in a function call in certain contexts. You have to use an extended > return statement though. > > See RM 6.5 (2.1/2) and 6.5 (28/2) for an example. > > That would allow the return object to be built in place where the > function result is to be placed, and thus avoids copying any object. > > Such a function that returns a limited type is usable only to initialize > a declaration of a limited type. You cannot use it to change the value > of the limited type once it has been initialized. This may be too > restrictive for your needs, so perhaps you should consider not making > this type limited. > Hm yes was peaking inside the double_linked_list provided with gnat, hoping to find something similar to my construction. I think I saw an example of what you mean. To complicate for the moment. Probably much easier to remove the limited. > This applies to an extended return statement. In your example, you are > using a simple return statement, if you want to use an extended return, > you need to use that syntax. > > The result subtype of your function is defined by a subtype_mark > (Iterator), so 6.5(5.2/2) is saying that the declaration of the result > object in the extended return must also be an Iterator, but you may > optionally add further constraints on the declaration. In your case, you > need to add a discriminant constraint for the access to the List > discriminant, since you want the result to have that value. > > eg. > > return Result (L) : Iterator do > null; > end return; Result(L): Iterator -- compiler not happy. Result: Iterator(L) do -- works. So I modified Iterator to private only and adapted the search function: function Search (L : access List; Element : Element_Type) return Iterator is It : Iterator (L); begin Start (It); while not Done (It) loop if Equals (It.This.Element, Element) then return Result : Iterator (L) do Result := It; end return; end if; Next (It); end loop; return Result : Iterator (L) do It.This:= null; Result := It; end return; end Search; Is that correct or just garbage. At least it compiles but that doesn't mean anything. Compiler is quite picky: It.This:= null; Result := It; That compiles but Result := null; won't, expecting Iterator getting access? Thanks for your patience Laurent ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-02-08 22:37 ` Laurent @ 2015-02-09 13:56 ` Brad Moore 2015-02-09 18:36 ` Laurent 0 siblings, 1 reply; 73+ messages in thread From: Brad Moore @ 2015-02-09 13:56 UTC (permalink / raw) On 15-02-08 03:37 PM, Laurent wrote: > On Saturday, February 7, 2015 at 11:14:46 PM UTC+1, Brad Moore wrote: > >> One way to get around this, is to define List_Ptr as a private type in >> the visible part of the package. >> >> eg. >> >> type List_Ptr is private; > > Ok that makes sense. As the package is based on an example from my Ada95 book, only the List type is visible. But the author had probably a good reason to design it like this? I believe you are referring to the example which appears on page 524 in John's 2005 book. I think it is generally desirable to not expose access types in the visible part of a package, and generally this should be possible. For a list package, exposing an Iterator or Cursor type is a cleaner approach, since you can hide any access values it may contain in the private part of the package. Users of the package have a nice Iterator abstraction without having to deal with access types and access values. In John's example, his Iterator type has an anonymous access discriminant pointing to a List object. This allows the user to declare Iterator objects and tie them to a List object. The discriminant is not mutable so once the Iterator is declared, it always points to that particular list object. I would probably go one step further and try to hide the discriminant and provide a function that accepts a List object as a parameter, and returns an Iterator object. This would be used to initialize a declaration of an iterator object. The Iterator could still have an anonymous access discriminant for a list in the private part, (or alternatively as a regular component of the Iterator object). If you want the Iterator to keep the discriminant, you can still hide it somewhat in the public part by declaring with unknown discriminants. i.e. type Iterator (<>) is limited private; This would also enforce that the only way to obtain an iterator would be through the function call. > >>> 65:20 (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2)) > > Oops wrong paragraphe, indeed meant 6.5(5.5/2) copied the wrong one > >> The compiler is complaining because you have declared It as a local >> object inside your Search function, and you are trying to return that >> object as the result of a function call, which involves copying the >> object to wherever the result of the function call is to be placed. >> >> Limited types are not copyable. Is there a reason why you declared your >> Iterator type to be a limited type, (ie. with the keyword limited)? > > No idea why it is limited. Took the example of the active iterator from John Barnes Ada 2005 book. > > But again I suppose that the author had a good reason to make the Iterator limited? He probably wanted to enforce that users of the package are not allowed to copy Iterator objects, or reinitialize them. A good design restriction as it might prevent users from using the abstraction is some ways that were not intended by the designer of the package. It's generally better to use limited types if you can live with the restrictions. In this case, the designer doesn't want the user to copy iterator objects, which seems like a reasonable restriction. If you want to avoid returning limited types from function calls, (and having to use extended return statements), you might want to consider passing the Iterator as an in out parameter to the call, as in John's example for his "Next" procedure. This avoids copying objects of limited type. > > Hm yes was peaking inside the double_linked_list provided with gnat, hoping to find something > similar to my construction. I think I saw an example of what you mean. To complicate for the > moment. Probably much easier to remove the limited. I'd suggest you keep the limited, but try the above >> eg. >> >> return Result (L) : Iterator do >> null; >> end return; > > Result(L): Iterator -- compiler not happy. > Result: Iterator(L) do -- works. Yes I realized that after I hit send. I figured you'd figure it out though, as you did. > > So I modified Iterator to private only and adapted the search function: > > function Search (L : access List; Element : Element_Type) return Iterator is > It : Iterator (L); > > begin > Start (It); > while not Done (It) loop > if Equals (It.This.Element, Element) then > return Result : Iterator (L) do > Result := It; > end return; Result.This := It.This; Instead of Result := It? If Iterator is no longer limited, then you could just use a simple return, i.e. return It; But keeping this as limited, I think it would be better as an in out parameter. Then the Search can be used on an Iterator object that already is declared. Returning as a function result means Search can only be used to initialize an Iterator object. > end if; > Next (It); > end loop; > return Result : Iterator (L) do > It.This:= null; > Result := It; > end return; > end Search; > > Is that correct or just garbage. At least it compiles but that doesn't mean anything. At first glance this looks OK, but I think you should consider rewriting as an in out parameter. I think you'll like the result better. > Compiler is quite picky: That's what's great about Ada. :-) > > It.This:= null; > Result := It; > > That compiles but Result := null; won't, expecting Iterator getting access? Result is a record type, not an access type, so setting it to null shouldn't be possible. Did you want Result.This := null; instead? Brad > > Thanks for your patience > > Laurent > ^ permalink raw reply [flat|nested] 73+ messages in thread
* Re: A few questions 2015-02-09 13:56 ` Brad Moore @ 2015-02-09 18:36 ` Laurent 0 siblings, 0 replies; 73+ messages in thread From: Laurent @ 2015-02-09 18:36 UTC (permalink / raw) > I believe you are referring to the example which appears on page 524 in > John's 2005 book. > Yes > Result.This := null; Yes found it out after a few hours of sleep. Happens quite often to me that I find the solution when I don't try to force it. Thanks for the detailed explanations. A lot of information to digest. Laurent ^ permalink raw reply [flat|nested] 73+ messages in thread
end of thread, other threads:[~2015-11-19 21:15 UTC | newest] Thread overview: 73+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-10-31 20:29 A few questions Laurent 2015-10-31 20:49 ` Dmitry A. Kazakov 2015-11-01 13:16 ` Laurent 2015-11-01 0:25 ` Jeffrey R. Carter 2015-11-01 13:30 ` Laurent 2015-11-03 6:25 ` Randy Brukardt 2015-11-01 9:05 ` Jacob Sparre Andersen 2015-11-01 13:40 ` Laurent 2015-11-01 18:14 ` Jacob Sparre Andersen 2015-11-01 18:40 ` Laurent 2015-11-01 13:42 ` brbarkstrom 2015-11-01 13:52 ` Laurent 2015-11-01 17:59 ` Jeffrey R. Carter 2015-11-01 18:35 ` Laurent 2015-11-02 13:25 ` brbarkstrom 2015-11-01 15:15 ` Dennis Lee Bieber 2015-11-01 16:33 ` gautier_niouzes 2015-11-01 16:36 ` gautier_niouzes 2015-11-01 18:17 ` Stephen Leake 2015-11-01 18:53 ` Laurent 2015-11-02 0:41 ` Dennis Lee Bieber 2015-11-02 16:42 ` Stephen Leake 2015-11-02 17:45 ` Simon Wright 2015-11-02 18:48 ` Simon Wright 2015-11-03 6:33 ` Randy Brukardt 2015-11-03 8:26 ` Simon Wright 2015-11-03 6:40 ` Randy Brukardt 2015-11-03 8:34 ` Simon Wright 2015-11-04 16:19 ` Simon Wright 2015-11-05 1:20 ` Randy Brukardt 2015-11-05 8:34 ` briot.emmanuel 2015-11-12 18:28 ` Randy Brukardt 2015-11-12 20:19 ` Simon Wright 2015-11-12 20:56 ` Dmitry A. Kazakov 2015-11-12 21:15 ` Randy Brukardt 2015-11-13 8:40 ` Dmitry A. Kazakov 2015-11-13 17:52 ` Randy Brukardt 2015-11-13 20:37 ` Dmitry A. Kazakov 2015-11-13 22:15 ` Randy Brukardt 2015-11-14 11:42 ` Dmitry A. Kazakov 2015-11-14 12:37 ` Simon Wright 2015-11-14 17:24 ` Shark8 2015-11-14 20:09 ` Simon Wright 2015-11-15 18:54 ` Brad Moore 2015-11-13 8:45 ` briot.emmanuel 2015-11-13 17:41 ` Randy Brukardt 2015-11-14 19:57 ` briot.emmanuel 2015-11-16 19:13 ` Randy Brukardt 2015-11-16 20:47 ` Dmitry A. Kazakov 2015-11-17 21:30 ` Randy Brukardt 2015-11-18 9:53 ` Dmitry A. Kazakov 2015-11-18 22:27 ` Randy Brukardt 2015-11-19 8:52 ` Dmitry A. Kazakov 2015-11-19 21:15 ` Randy Brukardt 2015-11-16 21:50 ` Simon Wright 2015-11-17 21:33 ` Randy Brukardt 2015-11-17 23:14 ` Simon Wright 2015-11-17 8:49 ` briot.emmanuel 2015-11-17 22:09 ` Randy Brukardt 2015-11-05 8:45 ` Simon Wright 2015-11-05 8:52 ` Simon Wright 2015-11-12 18:29 ` Randy Brukardt 2015-11-12 18:32 ` Randy Brukardt 2015-11-12 20:02 ` Simon Wright 2015-11-12 21:08 ` Randy Brukardt 2015-11-15 17:56 ` Brad Moore 2015-11-15 21:42 ` Simon Wright 2015-11-16 19:16 ` Randy Brukardt -- strict thread matches above, loose matches on Subject: below -- 2015-02-07 17:43 Laurent 2015-02-07 22:15 ` Brad Moore 2015-02-08 22:37 ` Laurent 2015-02-09 13:56 ` Brad Moore 2015-02-09 18:36 ` Laurent
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox