CVS difference for ai05s/ai05-0139-2.txt

Differences between 1.4 and version 1.5
Log of other versions for file ai05s/ai05-0139-2.txt

--- ai05s/ai05-0139-2.txt	2010/02/16 03:18:00	1.4
+++ ai05s/ai05-0139-2.txt	2010/02/23 07:31:06	1.5
@@ -20,10 +20,10 @@
 
 A better mechanism is required.
 
-In addition, using the notion of "accessors" or "references" as defined in AI05-0142
-is syntactically awkward. Finally, it is often clearer to iterate over the elements
-of a container (or array) directly, rather than iterating over a cursor (or index)
-into the container (or array).
+In addition, using the notion of "accessors" or "references" as defined in
+AI05-0142 is syntactically awkward. Finally, it is often clearer to iterate over
+the elements of a container (or array) directly, rather than iterating over a
+cursor (or index) into the container (or array).
 
 Using accessors for user-defined dereference (rather than simple access values
 as proposed in AI05-141) has the potential to provide a safer mechanism that
@@ -1433,5 +1433,1938 @@
 overkill to try to get it to work for containers as well.
 
 As usual, any and all comments welcome.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, February 11, 2010  7:19 AM
+
+I didn't like the "default iterator" solution in version 3, so here is version 4
+which uses the specification of two aspects, Default_Iterator and
+Iterator_Element, rather than the signature generic.  This makes the solution
+more palatable to me.  I recommend you ignore version 3.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 11, 2010  10:17 PM
+
+[The first of several free association thoughts on this proposal.]
+
+It would be appealing to define:
+
+   function "()" (S : Unbounded_String; I : Positive) renames Element;
+
+but unfortunately Unbounded_String is not tagged, so this doesn't work.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 11, 2010  10:23 PM
+
+> One relatively important rule for "()" is that one can define two
+> operators, one that requires the controlling operand to be a variable,
+> and one that allows it to be a constant, and overload resolution will
+> resolve to the one that requires a variable if the actual is a
+> variable, and otherwise it will resolve to the one that allows a
+> constant.  This rule is important so that the same notation, such as
+> "Container(Key)", can be used when Container is a constant as when it
+> is a variable, and the variableness of the result can be determined by
+> the variableness of the Container.
+
+Unfortunately, this is purely fantasy. Resolution rules do not take anything
+about constant vs. variable into account -- those are legality rules. Even if it
+wasn't fantasy, it still wouldn't make sense, since a variable can always be
+passed where a constant is allowed. It would seem odd to eliminate that.
+
+This seems like a downside of any proposal to eliminate the function names from
+calls. (Unless you are proposing a new kind of resolution to make this work; it
+would in fact make sense in this case, but I have to wonder about a preference
+rule since they're usually problematic.)
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 11, 2010  10:38 PM
+
+In your example, you have the following:
+
+>       function "()"(Tab : access T_Table; Key : String) return Ref_T;
+
+This works OK, but it is important to note that it isn't safe, in that the
+access value returned as the discriminant of Ref_T can outlive the Ref_T object
+(at least if I understand AI-51's model, which perhaps I don't in some subtle
+case).
+
+The "aliased" parameters of AI05-0142-4 were designed to eliminate that problem
+(and the need for dynamic accessibility checking). In that case, the
+specification would look like:
+
+       function "()"(Tab : aliased in out T_Table; Key : String) return Ref_T;
+
+I couldn't tell whether you were proposing that the original formulation was
+enough in all cases (which didn't seem to be the case last year, and I doubt
+that's changed), or whether you were just avoiding the AI-142-4 and AI-143
+features necessary to make the intended formulation work in the interest of
+avoiding mixing of a bunch of new features.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, February 12, 2010  6:34 AM
+
+I agree that "aliased in out" is preferable to "access"
+but I didn't want to tie the two AIs too closely at this point.  I don't believe
+there is a safety issue.  If there is, then AI-51 needs to be fixed.  I am
+certainly hoping we are going to tackle AI-51 at this meeting!
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, February 12, 2010  12:57 PM
+
+This syntactic sugar is really great!  I've been wanting things like this for a
+long time.
+
+Can we add user-defined literals to this AI, so unbounded strings can be
+tolerable?
+
+I'm disappointed that the "of" iterators require the cursor stuff.  It would be
+much cleaner to define them in terms of things like:
+
+   procedure Iterate
+        (Container : in Vector;
+         Process   : not null access procedure (Position : in Cursor));
+
+But I don't see how that can work, because then you can't "exit".
+Sigh.
+
+...
+> Using an iterator over one of the Ada 2005 containers libraries
+> requires writing a subprogram which gets called repeatedly with each element of the container.
+> That effectively requires writing the loop body out-of-line from the
+> loop, making the code inside-out of its normal flow, requiring the
+> writing of a lot of extra text, and thus making it much harder to read and understand.
+
+Not to mention having to give it a meaningless name.
+
+...
+>        type Ref_T(Data : access T) is
+>          new Ada.Finalization.Limited_Controlled
+>            and Ada.References.Reference with ...
+
+Why not "null record"?
+
+...
+>   package body Whatever is
+>        function Element(Tab : access T_Table; Key : String) return Ref_T is
+>           -- Return a "reference" to an element of the table
+>        begin
+>            -- "Wrap" the pointer in a reference object
+>            return Ref_T'(Data => Lookup(Tab, Key));
+
+Is Lookup_Or_Create meant?
+
+...
+>     package Whatever is
+>        ... as above
+>
+>        function "()"(Tab : access T_Table; Key : String) return Ref_T;
+
+Here and below, id the "access" significant?  Could it have been "in out"?
+
+...
+> The basic rule with "()" is that it must be suitable for prefix
+> notation, meaning that it is either a primitive operation or a
+> class-wide operation of some tagged type (via its first parameter),
+> and if class-wide, is declared immediately within a package where some
+> tagged type covered by the class-wide type is immediately declared.
+> It must have at least two parameters.  There seems no particular
+> reason it couldn't have more than two parameters.  There are no predefined "()"
+> operators, though one could imagine that all array types have such
+> operators, if it helps in understanding the model.
+
+It seems annoying to restrict it to tagged types.
+Is that really necessary?
+
+I see below that cursor types will have to be tagged to take advantage of this
+notation.  That's even more annoying, because cursors can often be quite
+lightweight.
+
+> One relatively important rule for "()" is that one can define two
+> operators, one that requires the controlling operand to be a variable,
+> and one that allows it to be a constant, and overload resolution will
+> resolve to the one that requires a variable if the actual is a
+> variable, and otherwise it will resolve to the one that allows a
+> constant.  This rule is important so that the same notation, such as
+> "Container(Key)", can be used when Container is a constant as when it
+> is a variable, and the variableness of the result can be determined by
+> the variableness of the Container.
+
+Well, that's a radical notion!  I see that it's necessary.
+
+Do you mean "allows a constant" or "requires a constant"?
+If the former, I think it introduces a Beaujolias effect.
+
+Would it make any sense to instead resolve on the basis of whether the context
+requires a variable? So for "X(C) := X(C) + 1;" the first would resolve to the
+variable one, and the second to the constant one.
+
+...
+> What the above presumes is that the function Iterate returns an object
+> of a type derived from a "magic" iterator type (see below).  The
+> iterator type provides a First and Next operation which return a
+> Cursor type, and a No_Element cursor value to indicate end of
+> iteration. The above expands into:
+>
+>    declare
+>       _Iter : Iterator_Type := Iterate(Container);
+>       Cursor : Cursor_Type := First(_Iter);
+>    begin
+>       while Cursor /= No_Element loop
+
+Are you sure you want to require every cursor type to have a special No_Element
+value?
+
+...
+> Note that the routines defined in this magic generic generally match
+> those used in iteration for the Ada.Containers packages, and their
+> meaning is the same. The only difference is that we've added an
+> iterator object parameter to the Next and Previous functions (which is
+> necessary to make them part of the interface).
+
+Are we going to add all this stuff to the existing container packages?
+
+...
+> This second syntax is more convenient, but less flexible, in that
+> there is no way to specify the particular iterator to use, so it
+> requires that there be a "default" iterator.
+
+Only for containers -- not arrays.
+
+...
+> The second requires an expression returning an array, or an object of
+> a type which has aspects Default_Iterator and Iterator_Element
+> specified.  The subtype_indication is optional, since the
+> Iterator_Element aspect of the container type determines the Element
+> type.  Similarly for an array, the Element type is simply the array
+> component type.  One purpose of the subtype_indication might be to
+> tighten the requirements on the elements of the container/array,
+> acting essentially as an assertion about the values stored in the
+> container/array at the time of the iteration.  Another purpose is
+> simply to help the reader, and provide an extra check that the
+> Iterator_Element type of the container is as expected.
+
+Hmm.  I'm inclined to always use a subtype_indication, for readability.  Should we require that?
+If so, we can change "OF" to "IN" in the syntax, which seems a slight improvement.
+
+...
+>    Vec : Int_Vectors.Vector;
+>    ...
+>    for X of Vec loop
+>           -- X renames Vec(<cursor>) where <cursor> in Default_Iterator(Vec).
+>           --    and Vec(<cursor>) is equiv to "()"(Vec, <cursor>).Discrim.all.
+>           -- X is a variable if Vec is a variable.
+>
+>        X := X + 1;
+>    end loop;
+>
+> The "of" syntax, suggested by J.P. Rosen, seems to help identify X as
+> an element *of* the array/container rather than as an index or cursor
+> *in* the sequence defined by the discrete range or iterator.
+
+For some reason, "of" rubs me the wrong way.  The elements are "in" the
+container, just as much as indices are "in" a range.
+
+I didn't read further, since you said you hadn't updated the rest.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, February 12, 2010  2:32 PM
+
+...
+> Can we add user-defined literals to this AI, so unbounded strings can
+> be tolerable?
+
+You don't like the "+" operator for this?
+
+I suppose we could define another new operator for something like this, or an
+aspect/attribute. If you have something in mind, go ahead and suggest it.  I'm
+pretty content with using "+".
+
+> I'm disappointed that the "of" iterators require the cursor stuff.  It
+> would be much cleaner to define them in terms of things like:
+>
+>    procedure Iterate
+>         (Container : in Vector;
+>          Process   : not null access procedure (Position : in Cursor));
+>
+> But I don't see how that can work, because then you can't "exit".
+> Sigh.
+
+You could have it take a function rather than a procedure, and return True or
+False to select "exit" or "continue".
+
+But you can also exit a loop prematurely using a "goto", a "return", a
+"requeue", an "exit" to an outer loop, etc. You put that all together and it
+creates a need to return a "continuation," and I think that is a bit too
+radical, even for Ada 2012. ;-)
+
+> ...
+>>    with Ada.References;
+>>    with Ada.Finalization;
+>>    package Whatever is
+>>        type T is private;
+>>        Null_T : constant T;  -- default initial value for T
+>>        function New_T(...) return T;
+>>
+>>        type T_Table is tagged limited private;
+>>
+>>        type Ref_T(Data : access T) is
+>>          new Ada.Finalization.Limited_Controlled
+>>            and Ada.References.Reference with ...
+>
+> Why not "null record"?
+
+That would probably work in many cases.
+It depends on what sort of cleanup action is required when the reference goes
+away.
+
+...
+>>   package body Whatever is
+>>        function Element(Tab : access T_Table; Key : String) return Ref_T is
+>>           -- Return a "reference" to an element of the table
+>>        begin
+>>            -- "Wrap" the pointer in a reference object
+>>            return Ref_T'(Data => Lookup(Tab, Key));
+>
+> Is Lookup_Or_Create meant?
+
+Oops, yes I meant Lookup_Or_Create.
+
+
+>>     package Whatever is
+>>        ... as above
+>>
+>>        function "()"(Tab : access T_Table; Key : String) return
+>> Ref_T;
+>
+> Here and below, id the "access" significant?  Could it have been "in
+> out"?
+
+I think the param might need to also be "aliased", and I didn't want to tie this
+too closely to the "aliased" parameter mode AI.
+
+>> The basic rule with "()" is that it must be suitable for prefix
+>> notation, meaning that it is either a primitive operation or a
+>> class-wide operation of some tagged type (via its first parameter),
+>> and if class-wide, is declared immediately within a package where
+>> some tagged type covered by the class-wide type is immediately
+>> declared.  It must have at least two parameters.  There seems no
+>> particular reason it couldn't have more than two parameters.  There are no predefined "()"
+>> operators, though one could imagine that all array types have such
+>> operators, if it helps in understanding the model.
+>
+> It seems annoying to restrict it to tagged types.
+> Is that really necessary?
+
+Probably not absolutely necessary.  Since we only have prefix notation for
+tagged types, it seemed natural to piggy-back on that.  But these are really
+pretty different, I suppose, so we could consider defining these for untagged
+types.
+
+> I see below that cursor types will have to be tagged to take advantage
+> of this notation.  That's even more annoying, because cursors can
+> often be quite lightweight.
+
+I didn't mean for cursors to have to be tagged.
+Where does that requirement come in?  It was not intentional.
+
+>> One relatively important rule for "()" is that one can define two
+>> operators, one that requires the controlling operand to be a
+>> variable, and one that allows it to be a constant, and overload
+>> resolution will resolve to the one that requires a variable if the
+>> actual is a variable, and otherwise it will resolve to the one that
+>> allows a constant.  This rule is important so that the same notation,
+>> such as "Container(Key)", can be used when Container is a constant as
+>> when it is a variable, and the variableness of the result can be
+>> determined by the variableness of the Container.
+>
+> Well, that's a radical notion!  I see that it's necessary.
+>
+> Do you mean "allows a constant" or "requires a constant"?
+> If the former, I think it introduces a Beaujolias effect.
+>
+> Would it make any sense to instead resolve on the basis of whether the
+> context requires a variable?
+> So for "X(C) := X(C) + 1;" the first would resolve to the variable
+> one, and the second to the constant one.
+
+That might be better.  I know this concerned Randy as well.
+I doubt if there is a Beaujolais effect, because this preference would
+presumably only apply to operators declared in the same scope.  If the
+preference might affect resolution across packages, that would definitely be an
+issue.
+
+I guess one important issue is whether this is a visibility issue at all.  This
+is more like the prefix-notation than like a visibility lookup.  So I see it
+more as "selecting" the right "()" operator rather than using normal overload
+resolution.  Clearly the devil will be in the wording for this one, if we decide
+we want this functionality.
+
+> ...
+>>    for Element of Arr loop
+>>        Element := Element + 1;
+>>    end loop;
+>>
+>> This second syntax is more convenient, but less flexible, in that
+>> there is no way to specify the particular iterator to use, so it
+>> requires that there be a "default" iterator.
+>
+> Only for containers -- not arrays.
+
+Correct.
+
+> ... The subtype_indication is optional, since the Iterator_Element
+>> aspect of the container type determines the Element type.  Similarly
+>> for an array, the Element type is simply the array component type.
+>> One purpose of the subtype_indication might be to tighten the
+>> requirements on the elements of the container/array, acting
+>> essentially as an assertion about the values stored in the
+>> container/array at the time of the iteration.  Another purpose is
+>> simply to help the reader, and provide an extra check that the
+>> Iterator_Element type of the container is as expected.
+>
+> Hmm.  I'm inclined to always use a subtype_indication, for
+> readability.  Should we require that?
+> If so, we can change "OF" to "IN" in the syntax, which seems a slight
+> improvement.
+
+I don't agree.  Making the presence of a subtype_indication completely change
+the meaning seems weird to me. I think we want the syntax distinction as well.
+
+...
+>> The "of" syntax, suggested by J.P. Rosen, seems to help identify X as
+>> an element *of* the array/container rather than as an index or cursor
+>> *in* the sequence defined by the discrete range or iterator.
+>
+> For some reason, "of" rubs me the wrong way.  The elements are "in"
+> the container, just as much as indices are "in" a range.
+
+I think you naturally talk about the elements "of" a container, at least as
+often as you talk about the elements "in" a container. For arrays, we talk about
+an array "of" integers, not an array "containing" integers.  I realize that is
+using "of" in the opposite sense, but "of" is a more symmetrical preposition
+than "in" in any case.  Anne of Green Gables.  Green Gables of Anne. Both make
+sense.  ;-)
+
+> I didn't read further, since you said you hadn't updated the rest.
+
+Right-O.  I actually tried to delete what wasn't applicable anymore, so the
+discussion and example sections are still worth reading, but they aren't
+complete at all.
+
+In any case, thanks for your careful reading of the new proposal section.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, February 12, 2010  3:28 PM
+
+> > Can we add user-defined literals to this AI, so unbounded strings
+> > can be tolerable?
+>
+> You don't like the "+" operator for this?
+
+I think it's an ugly hack.  But I do tolerate it.
+
+It's kind of annoying that this is a syntax error:
+
+   X : Unbounded_String := +"Hello";
+   Y : Unbounded_String := X & +", world.";
+
+> I suppose we could define another new operator for something like
+> this, or an aspect/attribute.
+> If you have something in mind, go ahead and suggest it.  I'm pretty
+> content with using "+".
+
+I don't like the "new operator" idea.  That's just a different-looking but equally-ugly hack.
+
+My idea would be to have an aspect like
+Literal_Value that's called implicitly, so:
+
+   X : T := "Hello";
+   Y : T2 := 123;
+
+is equivalent to
+
+   X : T := T'Literal_Value("Hello");
+   Y : T2 := T'Literal_Value("123");
+
+This AI is all about syntactic sugar, so I thought maybe I could sneak this in.  ;-)
+
+> > I'm disappointed that the "of" iterators require the cursor stuff.
+> > It would be much cleaner to define them in terms of things like:
+> >
+> >    procedure Iterate
+> >         (Container : in Vector;
+> >          Process   : not null access procedure (Position : in Cursor));
+> >
+> > But I don't see how that can work, because then you can't "exit".
+> > Sigh.
+>
+> You could have it take a function rather than a procedure, and return
+> True or False to select "exit" or "continue".
+
+So an "exit" in the loop would turn into "return True"?
+Hmm.  Maybe.  Doesn't work for nested loops.
+
+> But you can also exit a loop prematurely using a "goto", a "return", a
+> "requeue", an "exit" to an outer loop, etc.
+> You put that all together and it creates a need to return a
+> "continuation," and I think that is a bit too radical, even for Ada
+> 2012. ;-)
+
+Right, that's what I meant by "But I don't see how that can work".
+
+You just need coroutines, not the full mind-bending power of continuations, I
+think.
+
+It's disappointing, though, because it's often easier (and never harder) to
+write an iterator that way. Think about an iterator that's a recursive tree
+walk.  To implement the get-next-item style, you have to horse around with an
+explicit stack that is guaranteed to be both too small and too big (or too
+inefficient).
+
+> > It seems annoying to restrict it to tagged types.
+> > Is that really necessary?
+>
+> Probably not absolutely necessary.  Since we only have prefix notation
+> for tagged types, it seemed natural to piggy-back on that.  But these
+> are really pretty different, I suppose, so we could consider defining
+> these for untagged types.
+
+OK, good.  Let's try to do that.
+
+> >
+> > I see below that cursor types will have to be tagged to take
+> > advantage of this notation.  That's even more annoying, because
+> > cursors can often be quite lightweight.
+>
+> I didn't mean for cursors to have to be tagged.
+> Where does that requirement come in?  It was not intentional.
+
+They have to be tagged if you want to use "()", which I think is common, isn't
+it?
+
+> > Do you mean "allows a constant" or "requires a constant"?
+> > If the former, I think it introduces a Beaujolias effect.
+> >
+> > Would it make any sense to instead resolve on the basis of whether
+> > the context requires a variable?
+> > So for "X(C) := X(C) + 1;" the first would resolve to the variable
+> > one, and the second to the constant one.
+>
+> That might be better.
+
+But it doesn't work if you rename X(C), right?
+
+>...I know this concerned Randy as well.
+> I doubt if there is a Beaujolais effect, because this preference
+>would presumably only apply to operators declared in the  same scope.
+>If the preference might affect resolution  across packages, that would
+>definitely be an issue.
+
+It's still a Beaujolais effect if it's within the same package.  You could argue
+that such Beaujolais effects are not so bad.
+
+I'm thinking that you have just the constant one.
+X is a variable, and you say "Put(X(C));".
+Then you add the variable version of "()", and now it silently switches to that
+one (under one interpretation of your words).
+
+> I guess one important issue is whether this is a visibility issue at
+> all.  This is more like the prefix-notation than like a visibility
+> lookup.  So I see it more as "selecting" the right "()" operator
+> rather than using normal overload resolution.  Clearly the devil will
+> be in the wording for this one, if we decide we want this
+> functionality.
+
+Seems like we need this functionality, or the whole feature is rather crippled.
+
+> > Hmm.  I'm inclined to always use a subtype_indication, for
+> > readability.  Should we require that?
+> > If so, we can change "OF" to "IN" in the syntax, which seems a
+> > slight improvement.
+>
+> I don't agree.  Making the presence of a subtype_indication completely
+> change the meaning seems weird to me.
+> I think we want the syntax distinction as well.
+
+A matter of taste, I suppose.  (But ": subtype_indication"
+is syntax!)
+
+We could still consider requiring the subtype_indication and keep "of".  What do
+you think?  I'm not sure. Maybe there are cases where the type is so obvious you
+want to leave it out.
+
+> I think you naturally talk about the elements "of" a container, at
+> least as often as you talk about the elements "in" a container.
+> For arrays, we talk about an array "of" integers, not an array
+> "containing" integers.  I realize that is using "of" in the opposite
+> sense, but "of" is a more symmetrical preposition than "in" in any
+> case.  Anne of Green Gables.  Green Gables of Anne.
+> Both make sense.  ;-)
+
+Well, if nobody agrees with me, I'll give in.
+It's not important.  (Note that I still sometimes type "case X of^H^His" N years
+after leaving the Pascal world for Ada.  ;-))
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, February 12, 2010  3:38 PM
+
+> But you can also exit a loop prematurely using a "goto", a "return", a
+> "requeue", an "exit" to an outer loop, etc.
+> You put that all together and it creates a need to return a
+> "continuation," and I think that is a bit too radical, even for Ada
+> 2012. ;-)
+
+Actually, all you really need is an implementation of all those goto-like things
+in terms of exceptions.
+
+By the way, the most elegant iterators I've ever seen are in Sather, which is a
+little-known follow-on to Eiffel.  (I think Sather is the name of a tower near
+Stanford U.  Get it?)  A little too elegant, in fact.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, February 12, 2010  3:54 PM
+
+>> You don't like the "+" operator for this?
+>
+> I think it's an ugly hack.  But I do tolerate it.
+>
+> It's kind of annoying that this is a syntax error:
+>
+>    X : Unbounded_String := +"Hello";
+>    Y : Unbounded_String := X & +", world.";
+
+You presumably don't need to use "+" for an operand of "&" since you can
+overload that directly on String.
+
+>
+>> I suppose we could define another new operator for something like
+>> this, or an aspect/attribute.
+>> If you have something in mind, go ahead and suggest it.  I'm pretty
+>> content with using "+".
+>
+> I don't like the "new operator" idea.  That's just a different-looking
+> but equally-ugly hack.
+>
+> My idea would be to have an aspect like Literal_Value that's called
+> implicitly, so:
+>
+>    X : T := "Hello";
+>    Y : T2 := 123;
+>
+> is equivalent to
+>
+>    X : T := T'Literal_Value("Hello");
+>    Y : T2 := T'Literal_Value("123");
+>
+> This AI is all about syntactic sugar, so I thought maybe I could sneak
+> this in.  ;-)
+
+With a single Literal_Value aspect/attribute, it seems hard to know which of the
+following should be legal for a given type:
+
+    Y : T2 := "123";
+or
+    Y : T2 := 123;
+
+You might find my ideas about this in my pie-in-the-sky language "ParaSail"
+interesting:
+
+http://parasail-programming-language.blogspot.com/2009/12/parasail-character-string-and-numeric.html
+
+and
+
+http://parasail-programming-language.blogspot.com/2009/12/parasail-universal-types-in-annotations.html
+
+These rely on being able to specify universal types explicitly in the
+declarations of certain operators.  But perhaps something analogous could be
+done in Ada.
+
+> ...
+>>> It seems annoying to restrict it to tagged types.
+>>> Is that really necessary?
+>> Probably not absolutely necessary.  Since we only have prefix
+>> notation for tagged types, it seemed natural to piggy-back on that.
+>> But these are really pretty different, I suppose, so we could
+>> consider defining these for untagged types.
+>
+> OK, good.  Let's try to do that.
+>
+>>> I see below that cursor types will have to be tagged to take
+>>> advantage of this notation.  That's even more annoying, because
+>>> cursors can often be quite lightweight.
+>> I didn't mean for cursors to have to be tagged.
+>> Where does that requirement come in?  It was not intentional.
+>
+> They have to be tagged if you want to use "()", which I think is
+> common, isn't it?
+
+Only the container needed to be tagged, not the "index" type (which is where the
+Cursor fits in). If I stated otherwise, that wasn't my intent.
+
+>>> Do you mean "allows a constant" or "requires a constant"?
+>>> If the former, I think it introduces a Beaujolias effect.
+>>>
+>>> Would it make any sense to instead resolve on the basis of whether
+>>> the context requires a variable?
+>>> So for "X(C) := X(C) + 1;" the first would resolve to the variable
+>>> one, and the second to the constant one.
+>> That might be better.
+>
+> But it doesn't work if you rename X(C), right?
+
+Yes, in a rename you would clearly want to make it a variable if C were a
+variable, so you are back to looking at the variableness of C, so you might as
+well always use that as the determining factor.
+
+>> ...I know this concerned Randy as well.
+>> I doubt if there is a Beaujolais effect, because this preference
+>> would presumably only apply to operators declared in the same scope.
+>> If the preference might affect resolution across packages, that would
+>> definitely be an issue.
+>
+> It's still a Beaujolais effect if it's within the same package.  You
+> could argue that such Beaujolais effects are not so bad.
+
+I don't follow that.  You'll have to show me an example.
+
+> I'm thinking that you have just the constant one.
+> X is a variable, and you say "Put(X(C));".
+> Then you add the variable version of "()", and now it silently
+> switches to that one (under one interpretation of your words).
+
+Oh, I see.  That hardly seems like a maintenance issue.  That almost seems more
+like a feature.
+
+...
+>>> Hmm.  I'm inclined to always use a subtype_indication, for
+>>> readability.  Should we require that?
+>>> If so, we can change "OF" to "IN" in the syntax, which seems a
+>>> slight improvement.
+>> I don't agree.  Making the presence of a subtype_indication
+>> completely change the meaning seems weird to me.
+>> I think we want the syntax distinction as well.
+>
+> A matter of taste, I suppose.  (But ": subtype_indication"
+> is syntax!)
+>
+> We could still consider requiring the subtype_indication and keep
+> "of".  What do you think?  I'm not sure.
+> Maybe there are cases where the type is so obvious you want to leave
+> it out.
+
+For an array it would be annoying I would think to have to specify the component
+subtype in an iterator over its components, particularly if it is a long-winded
+name. It feels like an annoying "test" that doesn't (im)prove anything.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, February 12, 2010  3:44 PM
+
+...
+> My idea would be to have an aspect like Literal_Value that's called
+> implicitly, so:
+>
+>    X : T := "Hello";
+>    Y : T2 := 123;
+>
+> is equivalent to
+>
+>    X : T := T'Literal_Value("Hello");
+>    Y : T2 := T'Literal_Value("123");
+>
+> This AI is all about syntactic sugar, so I thought maybe I could sneak
+> this in.  ;-)
+
+I'm in favor of this idea. But we looked at it last time, and concluded that it
+would make most Unbounded_String operations ambiguous to call with literals. So
+the #1 use for it wouldn't work.
+
+Consider Append, for instance. It is defined as:
+
+ procedure Append (Source   : in out Unbounded_String;
+                   New_Item : in Unbounded_String); -- (1)
+
+ procedure Append (Source   : in out Unbounded_String;
+                   New_Item : in String); --(2)
+
+ procedure Append (Source   : in out Unbounded_String;
+                   New_Item : in Character);
+
+So a call
+
+    Append (UBS, "Whatever");
+
+works today.
+
+If you add an automatic conversion possibility, this call becomes ambiguous, as
+both (1) and (2) would match. The only way out would be a preference rule, and
+those are typically trouble.
+
+P.S. I'd rather discuss the various unrelated subjects separately, so that
+people can comment on the one thing that interests them and not a litany of
+other things. Thus several separate answers.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, February 12, 2010  4:03 PM
+
+> I'm in favor of this idea. But we looked at it last time, and
+> concluded that it would make most Unbounded_String operations
+> ambiguous to call with literals. So the #1 use for it wouldn't work.
+
+Good point.  And there is probably lots of existing code that has the same
+problem -- people add lots of overloadings precisely to get around the lack of
+user-defined literals.
+
+On the other hand, it would be useful for new packages.
+
+> If you add an automatic conversion possibility, this call becomes
+> ambiguous, as both (1) and (2) would match. The only way out would be
+> a preference rule, and those are typically trouble.
+
+Well, Tucker has argued recently that Beaujolais effects aren't so bad (or
+shouldn't be considered Beaujolais effects) if they're within a single package.
+Hmm...
+
+Or we could remove the offending overloadings.  That would be incompatible, but
+not very much so...
+
+Or we could add Ada.Strings.New_Improved_Unbounded_Strings.
+
+Only half kidding here...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, February 12, 2010  3:54 PM
+
+> > Probably not absolutely necessary.  Since we only have prefix
+> > notation for tagged types, it seemed natural to piggy-back on that.
+> > But these are really pretty different, I suppose, so we could
+> > consider defining these for untagged types.
+>
+> OK, good.  Let's try to do that.
+
+I think it would be a good idea, but I don't see any way to do that without
+losing all of the existing magic that Tucker is leaning on.
+
+Currently, he has:
+
+    Container(...) equivalent to  Container."()"(...)
+
+But of course the latter form isn't allowed for untagged types (for various good
+reasons).
+
+We could of course say the equivalence is instead to:
+
+    "()"(Container, ...)
+
+But that would prevent the use of the magic of prefix notation:
+(1) No use-clause needed for visibility;
+(2) Automatic lookup for class-wide operations;
+(3) Automatic addition of .all and 'Access as necessary.
+
+(2) of course doesn't matter for untagged types, but surely the other two do.
+Tucker's example in fact requires the automatic addition of 'Access. You'd never
+want to allow that on untagged types (unless the objects are aliased). We could
+duplicate all of that magic, but that seems like a mess. Or we could try to
+allow prefix notation on untagged types, but we already *know* that's a mess.
+
+> > > I see below that cursor types will have to be tagged to take
+> > > advantage of this notation.  That's even more annoying, because
+> > > cursors can often be quite lightweight.
+> >
+> > I didn't mean for cursors to have to be tagged.
+> > Where does that requirement come in?  It was not intentional.
+>
+> They have to be tagged if you want to use "()", which I think is
+> common, isn't it?
+
+You don't want to use "()" on a cursor, the cursor is the parameter. The
+parameter has no restrictions. And in any case, if you allow untagged "()"
+(which is appealing), then it doesn't matter.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, February 12, 2010  4:02 PM
+
+...
+> > > Do you mean "allows a constant" or "requires a constant"?
+> > > If the former, I think it introduces a Beaujolias effect.
+> > >
+> > > Would it make any sense to instead resolve on the basis of whether
+> > > the context requires a variable?
+> > > So for "X(C) := X(C) + 1;" the first would resolve to the variable
+> > > one, and the second to the constant one.
+> >
+> > That might be better.
+>
+> But it doesn't work if you rename X(C), right?
+
+I read this whole section as meaning that resolution already did this, not that
+you were proposing to change resolution.
+
+> >...I know this concerned Randy as well.
+> > I doubt if there is a Beaujolais effect, because this preference
+> >would presumably only apply to operators declared in the same scope.
+> >If the preference might affect resolution  across packages, that
+> >would definitely be an issue.
+>
+> It's still a Beaujolais effect if it's within the same package.  You
+> could argue that such Beaujolais effects are not so bad.
+
+But the "()" doesn't have to be in the same package, it just has to be in an
+ancestor (think class-wide lookup). And if you have two forms, they could be in
+different packages.
+
+Note that the alternative of *requiring* const/var matching would be pain if all
+you want is to define read access (which I think will be fairly common). In that
+case you'd still need to define two routines with the same result type.
+
+We could "fix" both problems by getting rid of the classwide lookup and
+requiring both routines to always be declared together (only as primitive
+operations of a type, and both are required). That seems like overkill, however.
+
+> I'm thinking that you have just the constant one.
+> X is a variable, and you say "Put(X(C));".
+> Then you add the variable version of "()", and now it silently
+> switches to that one (under one interpretation of your words).
+
+Right. The rule I suggest above would fix that, by not allowing there not to be
+a variable one. But it would clearly be a pain.
+
+> > I guess one important issue is whether this is a visibility issue at
+> > all.  This is more like the prefix-notation than like a visibility
+> > lookup.  So I see it more as "selecting" the right "()" operator
+> > rather than using normal overload resolution.  Clearly the devil
+> > will be in the wording for this one, if we decide we want this
+> > functionality.
+>
+> Seems like we need this functionality, or the whole feature is rather
+> crippled.
+
+That's true, it's more like prefix-notation of an operator. One could simply
+duplicate the whole set of rules for prefix calls, and change the ones that we
+don't like or need. Sounds like a bigger mess, though.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, February 12, 2010  4:08 PM
+
+Can you remind me of some of the "good reasons"
+why prefix notation is not permitted for untagged types?  I can't remember the
+trouble they caused...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, February 12, 2010  4:31 PM
+
+> Can you remind me of some of the "good reasons"
+> why prefix notation is not permitted for untagged types?  I can't
+> remember the trouble they caused...
+
+Gee, I don't remember either. I just remember we had problems and eventually
+gave up and just restricted to tagged. Better go look in the old AIs. Nice that
+we index them from the text changes: the numbers in question are AI95-0252 and
+AI95-0407 (based on 4.1.3(9.2/2) - there's a more recent fix to that, too, but
+it's not relevant).
+
+AI-0252 just has a paragraph at the end of the discussion:
+
+  We originally generalized this to support non-tagged types, but the
+  added complexity this brought to handling access types seemed more than
+  the anticipated benefit, since we would have to consider primitives of the
+  access type itself as well as those of its designated type.
+
+I think the problem comes about because of the automatic dereference. And I
+recall some pretty hairy examples of what that would cause. Probably have to go
+look up the minutes and/or read the old e-mail to recall the full extent. I'll
+leave that to you. (It strikes me that limiting "()" to composite types might
+effectively fix that problem.)
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, February 12, 2010  5:31 PM
+
+I also remember it being related to access types.
+If we stick to composite types for "()" that would seem to avoid the problem.
+Of course a private type might turn out to be an access type.  Not sure what
+mischief that would cause...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February 15, 2010  10:17 PM
+
+> I also remember it being related to access types.
+> If we stick to composite types for "()" that would seem to avoid the
+> problem.  Of course a private type might turn out to be an access
+> type.  Not sure what mischief that would cause...
+
+I thought of that, too. But I don't think that has to be a problem; "()" has to
+be primitive as you currently have it, and thus we could make it illegal to
+define it on an elementary type (even if we don't find out the type is
+elementary until the full definition -- it still has to be in the same package).
+I don't think that there is a problem if you *never* know that the type is
+elementary:
+
+    package P is
+       type Priv is private;
+    private
+       type Priv is access ...
+    end P;
+
+    with P;
+    package Q is
+       type My_Type is new P.Priv;
+       function "()" (O : aliased in out My_Type; ...)...
+    end Q;
+
+My_Type will never appear to be an access type to any user, even in the body of
+P, so you'll never have to consider ".all" of it.
+
+But this is sort of a last resort; if we can find a way to make these work
+without such a rule, that would be better still.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Friday, February 12, 2010  12:57 PM
+
+> >    Y : Unbounded_String := X & +", world.";
+>
+> You presumably don't need to use "+" for an operand of "&" since you
+> can overload that directly on String.
+
+True, but the whole point of having user-defined literals is to avoid having so
+many overloadings that just do "convert some args from String to T and then do
+the real work".
+
+> With a single Literal_Value aspect/attribute, it seems hard to know
+> which of the following should be legal for a given type:
+>
+>     Y : T2 := "123";
+> or
+>     Y : T2 := 123;
+
+Maybe both?
+
+> You might find my ideas about this in my pie-in-the-sky language
+> "ParaSail" interesting:
+
+I'm sure I would.  I keep intending to pay attention to that, but I never seem
+to find the time.
+
+By the way, a blog seems like a rather unsuitable way to communicate a language
+design.  How about giving me a Parasail Reference Manual?  ;-)
+
+> Only the container needed to be tagged, not the "index" type (which is
+> where the Cursor fits in).
+> If I stated otherwise, that wasn't my intent.
+
+I guess I misunderstood.
+
+> > I'm thinking that you have just the constant one.
+> > X is a variable, and you say "Put(X(C));".
+> > Then you add the variable version of "()", and now it silently
+> > switches to that one (under one interpretation of your words).
+>
+> Oh, I see.  That hardly seems like a maintenance issue.  That almost
+> seems more like a feature.
+
+Perhaps it is.
+
+By the way, I guess you're normally going to have two "()" ops, and their bodies
+are going to be identical.  That's a little bit annoying.
+
+> For an array it would be annoying I would think to have to specify the
+> component subtype in an iterator over its components, particularly if
+> it is a long-winded name.
+> It feels like an annoying "test" that doesn't (im)prove anything.
+
+Well, I suppose can buy that, but I'm not sure why you say "For an array".  If
+it's annoying, isn't it equally annoying for any container-of-T, to have to
+specify T?
+
+Anyway, I'm happy to be _allowed_ to specify T.
+I think "for C: Character of S loop" is nicely readable.
+
+When I do "Iterate(X, Action => Blah'Access);" I am annoyed that Blah is in the
+wrong place, and that it's not anonymous, and that I have to say 'Access.  But
+I'm not particularly annoyed that Blah's parameter's type is explicit.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, February 12, 2010   7:48 PM
+
+> True, but the whole point of having user-defined literals is to avoid
+> having so many overloadings that just do "convert some args from
+> String to T and then do the real work".
+
+OK, but you started this discussion with add this "so unbounded strings can be
+tolerable". But unbounded string *have* all of those overloadings, and we surely
+aren't going to remove them (the compatibility cost would be horrendous).
+
+Now, it would make sense to create a new package by taking Unbounded_Strings,
+giving the package a new name, replacing all occurrences of "String" by
+"Unbounded_String", and removing all of the duplicate routines. (We have to do
+this replacement because there are a number of routines that *only* take String
+parameters, and those have to be converted.) Then adding the new "()" and
+literals routines. But I tried such a suggestion last time and it got no
+traction (I was told "Unbounded_Strings" is good enough). And we tried a
+proposal much like this and abandoned it because it wouldn't help
+Unbounded_Strings.
+
+Thus I can see why this would be a good idea, but since we wouldn't be able to
+use it for anything (predefined), it's hard to imagine that it would be worth
+the effort.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Friday, February 12, 2010  10:49 PM
+
+> By the way, I guess you're normally going to have two "()" ops, and
+> their bodies are going to be identical.  That's a little bit
+> annoying...
+
+I don't see them as identical in some cases.
+A read-only reference can be cheaper to manage than a read-write reference.
+There may be less or different locking, and if you are talking about a
+persistent data structure, there is no need to mark the page with the given
+element as "dirty" if the reference is read-only.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February 15, 2010  10:18 PM
+
+> I also remember it being related to access types.
+> If we stick to composite types for "()" that would seem to avoid the
+> problem.  Of course a private type might turn out to be an access
+> type.  Not sure what mischief that would cause...
+
+I thought of that, too. But I don't think that has to be a problem; "()" has to
+be primitive as you currently have it, and thus we could make it illegal to
+define it on an elementary type (even if we don't find out the type is
+elementary until the full definition -- it still has to be in the same package).
+I don't think that there is a problem if you *never* know that the type is
+elementary:
+
+    package P is
+       type Priv is private;
+    private
+       type Priv is access ...
+    end P;
+
+    with P;
+    package Q is
+       type My_Type is new P.Priv;
+       function "()" (O : aliased in out My_Type; ...)...
+    end Q;
+
+My_Type will never appear to be an access type to any user, even in the body of
+P, so you'll never have to consider ".all" of it.
+
+But this is sort of a last resort; if we can find a way to make these work
+without such a rule, that would be better still.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Wednesday, February 17, 2010  11:33 PM
+
+> > As usual, any and all comments welcome.
+
+I am very much in favor of the intent behind this proposal.
+
+I have have some suggestions however, that might further improve things. I admit
+I haven't fully thought these ideas through, but I wanted to see if they had any
+appeal.
+
+In a nutshell, if possible, I would like to see;
+  1) Syntax even more harmonious with existing array/iterator syntax.
+  2) An optional extension to the existing loop syntax to allow more
+  than one type of "magic" expansion. Essentially, allowing the
+  programmer to provide/override the implementation of the loop.
+
+For point 1, I am wondering if it would make sense to have syntax like;
+
+    for I in Container'Range loop
+       Container (I) := Container (I) + 1;
+    end loop;
+
+    instead of;
+
+    for Cursor in Iterate(Container) loop
+        Container(Cursor) := Container(Cursor) + 1;
+    end loop;
+
+
+    This would be more in line with existing syntax for iterating
+    through arrays. In this idea, the 'Range attribute would be user
+    definable for a container. Something like;
+
+package Ada.Containers.Doubly_Linked_Lists is
+
+   type List is tagged private;
+   type Cursor is private;
+
+   function First (Container : List) return Cursor;
+   function Last (Container : List) return Cursor;
+
+   package List_Range is new Ada.Range_Attribute
+     (Index_Type => Cursor,
+      Start => First,
+      Finish => Last);
+   for List'Range use List_Range.Magical_Thingy
+
+
+If such a construct is even possible, then perhaps one could also write
+
+    Position1 : Cursor := ...;
+    Position2 : Cursor := ...;
+
+    for I in Position1 .. Position2 loop
+       Container (I) := Container (I) + 1;
+    end loop;
+
+    Which seems useful.
+
+> a) The first syntax is intended for iterating over the set of cursors
+> or indices that select elements of a container.  This is most
+> analogous to what is already available for arrays by writing "for I in
+> Arr'Range loop":
+>
+>    for Cursor in Iterate(Container) loop
+>        Container(Cursor) := Container(Cursor) + 1;
+>    end loop;
+>
+> What the above presumes is that the function Iterate returns an object
+> of a type derived from a "magic" iterator type (see below).  The
+> iterator type provides a First and Next operation which return a
+> Cursor type, and a No_Element cursor value to indicate end of
+> iteration. The above expands into:
+>
+>    declare
+>       _Iter : Iterator_Type := Iterate(Container);
+>       Cursor : Cursor_Type := First(_Iter);
+>    begin
+>       while Cursor /= No_Element loop
+>          Container(Cursor) := Container(Cursor) + 1;
+>            -- This presumes an appropriate "()" operator
+>            -- is defined.
+>
+>          Cursor := Next(_iter, Cursor);
+>       end loop;
+>    end;
+>
+
+Could not this also expand to;
+
+   declare
+      procedure Iterate (Position : Lists.Cursor) is
+      begin
+         Container (Cursor) := Container (Cursor) + 1;
+      end Iterate;
+   begin
+      Container.Iterate (Iterate'Access);
+   end;
+
+Then there is less "magic" needed it seems to me.
+There is no need to involve an iterator interface with a function returning the
+First cursor, and other function returning the Next.
+
+This way, the expansion also works for containers where it doesn't make as much
+sense to start at the first element. For example, a recursive binary tree
+container would probably want to start the iteration at the root node of the
+tree, rather than start at the left most leaf node. If we can assume such an
+Iterate function has been defined, then the container implementation can decide
+how best to iterate through the container. As a further example, I have
+implemented a parallel recursive binary tree container which makes even less
+sense to think of starting the iteration at First, and iterating through the
+elements using Next. I do provide an Iterate procedure that manages the
+parallelism.
+
+> b) The second syntax is intended for iterating directly over the
+> elements of a container or an array:
+>
+>    for Element of Container loop
+>        Element := Element + 1;
+>    end loop;
+>
+> or
+>
+>    for Element of Arr loop
+>        Element := Element + 1;
+>    end loop;
+>
+
+These forms could also expand to the same expansion I suggested above, could
+they not?
+
+----------------
+
+Now the the second main suggestion.
+
+I would ideally like to see flexibility in the syntax so that the compiler could
+generate different expansions depending on the magical interface utilized by the
+programmer. For example, the expansions so far discussed in this AI center
+around making it easier to write iterators for containers, using a sequential
+approach. I would ideally like to be able to see expansions that would allow
+parallel executions through loops, including containers, arrays, and simple
+loops. The idea is that loop syntax would allow the programmer to optionally
+specify the name of a procedure/function used to implement the loop. Perhaps
+this procedure or function would be associated with a magical interface from a
+set of several available/defined interfaces so that the interface associated
+with the procedure would indicate to the compiler how the code should be
+expanded.
+
+For example,
+For the case of sequentially iterating through a container, one could optionally
+write something like;
+
+    for I in Container'Range with Container.Iterate loop
+       Container (I) := Container (I) + 1;
+    end loop;
+
+The with clause allows the programmer to specify the name of the procedure
+(implementation) to use for executing the iteration. This could default to name
+a primitive of the container such as "Iterate", which would be used if this was
+not specified by the programmer.
+
+i.e.
+    for I in Container'Range loop
+      ...
+
+    implies "with Container.Iterate" since that was not specified.
+
+
+Perhaps a different expansion would be like the one Tucker suggests for when you
+have a container where First and Next make sense, and where we would not want to
+expose an Iterate procedure, since the new syntax makes it easier to iterate
+through the container.
+
+Now consider a simple loop that we would like to execute in parallel.
+
+declare
+   Sum : Integer := 0;
+begin
+   for I in 1 .. 100_000_000 loop
+      Sum := Sum + I;
+   end loop
+end;
+
+We could use similar syntactic sugar to allow the programmer to write this as
+something like;
+
+with Integer_Addition_Reducer;
+-- an instantiation of a generic procedure
+
+declare
+   Sum : Integer := 0;
+begin
+   for I in 1 .. 100_000_000 with Integer_Addition_Reducer <Sum> loop
+       Sum := Sum + I;
+   end loop
+end;
+
+In this fantasy syntax, the variables enclosed by angle brackets (if
+any) represent variables that are modified by the loop but are declared in scope
+outside the loop. The generic needs to treat these specially to avoid race
+conditions when executing the loop in parallel.
+
+This might expand to;
+
+declare
+   Sum : Integer := 0;
+begin
+   declare
+      procedure Iteration (Start, Finish : Positive; Sum : in out Integer) is
+      begin
+         for I in Start .. Finish loop
+            Sum := Sum + I;
+         end loop;
+      end Iteration;
+   begin
+      Integer_Addition_Reducer
+        (From    => 1,
+         To      => 100_000_000,
+         Process => Iteration'Access,
+         Item    => Sum);
+   end;
+
+I am currently working on a paper that utilizes such generics to assist in
+writing parallel loop iterations and parallel recursion. I am planning to
+present this at Ada Europe in Valencia, if anyone is interested. While I see
+these generics being useful without the benefit of syntactic sugar, some added
+sweetener would be nice, particularly if it is compatible with whatever syntax
+is used for regular container iterators.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 18, 2010  12:47 AM
+
+...
+> > > As usual, any and all comments welcome.
+>
+> I am very much in favor of the intent behind this proposal.
+
+Good.
+
+> I have have some suggestions however, that might further improve
+> things. I admit I haven't fully thought these ideas through, but I
+> wanted to see if they had any appeal.
+...
+> For point 1, I am wondering if it would make sense to have syntax
+> like;
+>
+>     for I in Container'Range loop
+>        Container (I) := Container (I) + 1;
+>     end loop;
+>
+>     instead of;
+>
+>     for Cursor in Iterate(Container) loop
+>         Container(Cursor) := Container(Cursor) + 1;
+>     end loop;
+
+Not really. The first form would only allow one iterator per container, and that
+would be a mistake. For instance, in the multiway tree containers, you might
+want to iterate on a particular set of children (starting from a particular
+node) or on the entire tree. That implies that we need multiple iterators and we
+need the capability of additional parameters. You also want the possibility of
+local storage for the iterator (such storage can't be in the container or you
+are restricting yourself to a single iteration at a time).
+
+Also recall that we have prefix notation, so the proposed form could easily be
+written:
+
+     for I in Container.Iterate loop
+         Container(I) := Container(I) + 1;
+     end loop;
+
+which is hardly different.
+
+...
+> If such a construct is even possible, then perhaps one could also
+> write
+>
+>     Position1 : Cursor := ...;
+>     Position2 : Cursor := ...;
+>
+>     for I in Position1 .. Position2 loop
+>        Container (I) := Container (I) + 1;
+>     end loop;
+>
+>     Which seems useful.
+
+You can write such an iterator easily. Indeed, I proposed one for the list
+container:
+
+     for I in Container.Partial_Iterate (Position1, Position2) loop
+        Container (I) := Container (I) + 1;
+     end loop;
+
+Here I'm using the possibility for parameters to the iterator creation function
+to control the iteration.
+
+...
+> Could not this also expand to;
+>
+>    declare
+>       procedure Iterate (Position : Lists.Cursor) is
+>       begin
+>          Container (Cursor) := Container (Cursor) + 1;
+>       end Iterate;
+>    begin
+>       Container.Iterate (Iterate'Access);
+>    end;
+
+No, as Bob and Tucker were talking about the other day, the loop has to support
+Exit (including multi-level exits) and Goto and all of the other transfers of
+control. A goto can't leave a subprogram body!
+
+...
+> This way, the expansion also works for containers where it doesn't
+> make as much sense to start at the first element. For example, a
+> recursive binary tree container would probably want to start the
+> iteration at the root node of the tree, rather than start at the left
+> most leaf node.
+
+I don't see this, as you can define First however you need for the iterator
+object. An iterator is *not* a container, and you don't have to use the same
+definition of First for the iterator as for the container. As Tucker notes,
+there is a single default iterator that allows you to use special syntax, but
+that is far too limiting for a general concept.
+
+> If we can
+> assume such an Iterate function has been defined, then the container
+> implementation can decide how best to iterate through the container.
+
+That's already true; the "Next" function can do whatever is appropriate for a
+particular iterator. It doesn't have to iterate in a particular order (although
+I would expect that most iterators would indeed have such an order).
+
+> As a further example, I have
+> implemented a parallel recursive binary tree container which makes
+> even less sense to think of starting the iteration at First, and
+> iterating through the elements using Next. I do provide an Iterate
+> procedure that manages the parallelism.
+
+A procedure seems appropriate for that, as it must not have an dependency
+between iterators nor any transfers of control. With a procedure body,
+dependencies are tough to write and exceptions are the only transfer of control.
+The body of a loop is a very different animal; it's easily nested in a declare
+block, and exits and returns are commonly used.
+
+> These forms could also expand to the same expansion I suggested above,
+> could they not?
+
+No, for the same reasons as noted above.
+
+> ----------------
+>
+> Now the the second main suggestion.
+>
+> I would ideally like to see flexibility in the syntax so that the
+> compiler could generate different expansions depending on the magical
+> interface utilized by the programmer. For example, the expansions so
+> far discussed in this AI center around making it easier to write
+> iterators for containers, using a sequential approach.
+> I would ideally like to be able to see expansions that would allow
+> parallel executions through loops, including containers, arrays, and
+> simple loops. The idea is that loop syntax would allow the programmer
+> to optionally specify the name of a procedure/function used to
+> implement the loop.
+> Perhaps this procedure or function would be associated with a magical
+> interface from a set of several available/defined interfaces so that
+> the interface associated with the procedure would indicate to the
+> compiler how the code should be expanded.
+
+I think that parallel loops would need to be syntactically marked, since the
+loop bodies would have to be written with a restricted set of features: no
+dependence between iterations, use of atomic variables/protected objects for
+sums and the like, and limited or no transfers of control. In an ideal world,
+those restrictions would be enforced by the compiler.
+
+> For example,
+> For the case of sequentially iterating through a container, one could
+> optionally write something like;
+>
+>     for I in Container'Range with Container.Iterate loop
+>        Container (I) := Container (I) + 1;
+>     end loop;
+
+Huh? Now you're proposing something more complex to write and use than the
+current proposal, which is:
+
+     for I in Container.Iterate loop
+        Container (I) := Container (I) + 1;
+     end loop;
+
+And if you want to use another iterator for the same container:
+
+    for I in Container.Child_Iterate (Some_Cursor) loop
+        Container (I) := Container (I) + 1;
+    end loop;
+
+You're setting up a straw man and then knocking it down and proposing something
+more complex.
+
+A parallel loop construct isn't a bad idea, but it doesn't make much sense by
+itself. You'd want to define other constructs that also could be executed in
+parallel (parallel blocks and the like). Remember that Ada doesn't allow
+anything to be executed in parallel other than tasks; you'd surely want to be
+able to make function calls in parallel. And for all of those things, you'd want
+to define various restrictions on the statements in the loop/block/subprogram
+body. That requires dedicated syntax so that the compiler and/or reader can know
+about those restrictions.
+
+Please don't kill this nice sequential proposal by loading up all kinds of
+parallel cruft on it.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, February 18, 2010  8:09 AM
+
+I agree with Randy's comments on Brad's suggestions.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Thursday, February 18, 2010  9:30 PM
+
+> > By the way, I guess you're normally going to have two "()" ops, and
+> > their bodies are going to be identical.  That's a little bit
+> > annoying...
+>
+> I don't see them as identical in some cases.
+> A read-only reference can be cheaper to manage than a read-write
+> reference.  There may be less or different locking, and if you are
+> talking about a persistent data structure, there is no need to mark
+> the page with the given element as "dirty" if the reference is
+> read-only.
+
+I've been thinking about this problem some more. I had almost convinced myself
+that this would work with some tweaks when I realized that there is an
+additional problem with this idea of having two function "()"s differing only by
+the constantness of the first parameter: we would have to allow homographs to be
+declared. For instance:
+    function "()" (Container : access constant Integer_Container; Index : in Natural) return Integer;
+and
+    function "()" (Container : access Integer_Container; Index : in Natural) return Integer;
+are homographs. In order for this resolution trick to work, we'd have to allow
+homographs (preferably only in this particular case!).
+
+That doesn't have much impact on the intended use, presuming that we give the
+prefix form Obj(Ind) special powers.
+
+However, it does have an impact on other uses of the functions. Any uses of the
+name "()" or Pack."()" are going to be ambiguous, because there will be two
+matching homographs (resolution uses type conformance to tell differences, which
+these surely are). For instance, normal calls like
+   Pack."()"(Obj, Ind);
+won't resolve.
+
+We could solve that by making the resolution rules depend on the name of the
+subprogram (which seems like a nasty wart - renames would work differently than
+the original subprograms), or by making a more general resolution change (which
+surely would have Beuajolias effects and possibly incompatibilities).
+
+We would also have similar problems with renames and uses as generic formal
+parameters. (The last isn't particularly important because a formal parameter
+couldn't be named "()" -- it is never primitive. But that too is weird.)
+
+I'm wondering if the proposal has gone off the rails a bit here by trying to
+have this new kind of subprogram with special resolution. It would be better if
+such magic was completely confined to the index-like call (which is new and
+isn't going to be a compatibility problem). As soon as we have an equivalent
+"normal" call, things start getting messy.
+
+So I've been thinking about alternatives. The obvious one would be to make these
+things a pair of aspects (I'm thinking "Variable_Indexing" and
+"Constant_Indexing"). Using aspects has several advantages:
+ * The routines are clearly tied to the type, so there isn't any big problem
+   supporting untagged types (or even scalar types);
+ * For normal calls, users use the "real" name of the functions, so there isn't
+   any resolution changes beyond the new magic notation;
+ * We don't need any funny rules about where the routines are declared -- the
+   need to specify the aspects would provide the appropriate result;
+ * It's not a problem to give the same function (name) to both aspects, so there
+   is no need to worry about having to duplicate the body;
+ * Legality of calls would depend only on whether an appropriate profile exists
+   for the appropriate aspect (and of course the normal rules for parameters);
+ * Changing the aspects of a type declaration surely has the possibility of
+   causing errors/changes down the line -- there is no doubt that it isn't
+   Beaujolais or anything like it.
+
+OTOH, these would be pretty weird aspects:
+ * The profile isn't fixed; it only needs the first parameter to be of the type;
+ * There shouldn't be any limit to the number of routines specified; the only
+   requirement beyond the first bullet is that the routines are not homographs.
+
+If we were to go this way, the "magic" *indexed call* would have at most two
+possible places to look for an operation: at the aspects of the prefix type, and
+if that is an access type, at the aspects of the designated type of the prefix
+type. The aspect to use would depend on whether or not the view of the prefix is
+a constant view (note that the object itself and the designated type could
+differ on that: dereferencing an access-to-constant variable would give a
+constant view.) Neither of these seem to have any particular difficulty. That
+would give one a set of profiles to resolve in the typical way: and no
+significant changes to resolution.
+
+One could imagine that arrays have a predefined version of these index aspects,
+with the obvious semantics; that would unify the syntax/semantics and avoid
+problems if someone tries to define these on an array type (otherwise we'd
+potentially have an ambiguity). Those would name a pair of anonymous functions
+like:
+
+    function <Constant_Indexing> (Arr : in Array_Type; Index : in
+Index_Subtype) return Component_Type;
+    function <Variable_Indexing> (Arr : access Array_Type; Index : in
+Index_Subtype) return access Ref_Component_Type;
+
+(The latter is a reference type.)
+
+If we go this way, I wonder if we would want a way to specify this aspect in
+generic contracts (it might make sense to be able to using indexing calls in a
+generic body).
+
+Anyway, food for thought.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, February 18, 2010  10:23 PM
+
+I agree the "()" idea seems to be creating several resolution issues.  Using an
+aspect specification may be cleaner.  If we are using an aspect specification
+for the Default_Iterator, it might be preferable to stick with that approach for
+other syntactic sugaring.  The aspect specification might just be specifying the
+name of the Variable_Indexing and Constant_Indexing functions, which could then
+be overloaded as desired to provide multiple indexing functions.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Friday, February 19, 2010  10:38 PM
+
+> > This way, the expansion also works for containers where it doesn't
+> > make as much sense to start at the first element. For example, a
+> > recursive binary tree container would probably want to start the
+> > iteration at the root node of the tree, rather than start at the
+> > left most leaf node.
+>
+> I don't see this, as you can define First however you need for the
+> iterator object. An iterator is *not* a container, and you don't have
+> to use the same definition of First for the iterator as for the
+> container. As Tucker notes, there is a single default iterator that
+> allows you to use special syntax, but that is far too limiting for a
+> general concept.
+
+I was thinking of a *recursive* binary tree container. I am having a difficult
+time seeing how one could use First and Next recursively to iterate through a
+tree. It is fairly easy to iterate through a tree non-recursively, and return a
+cursor to where the iteration last left off, and then picking up from where the
+iteration left off, with a call to Next. But I think this would be hard to do
+using a recursive stack-based approach. I suppose though, that for such a
+container, one would just have to use the Iterate procedure and not bother with
+this iterator syntax. If someone really wants to support the iterator syntax for
+such a container, they could provide a non-recursive First and Next as you
+suggest.
+
+> > As a further example, I have
+> > implemented a parallel recursive binary tree container which makes
+> > even less sense to think of starting the iteration at First, and
+> > iterating through the elements using Next. I do provide an Iterate
+> > procedure that manages the parallelism.
+>
+> A procedure seems appropriate for that, as it must not have an
+> dependency between iterators nor any transfers of control. With a
+> procedure body, dependencies are tough to write and exceptions are the
+> only transfer of control.
+
+Perhaps the proposed Preconditions, Postconditions would make it easier to
+specify the dependency rules.
+
+
+> I think that parallel loops would need to be syntactically marked,
+> since the loop bodies would have to be written with a restricted set
+> of features: no dependence between iterations, use of atomic
+> variables/protected objects for sums and the like, and limited or no
+> transfers of control. In an ideal world, those restrictions would be
+> enforced by the compiler.
+
+> A parallel loop construct isn't a bad idea, but it doesn't make much
+> sense by itself. You'd want to define other constructs that also could
+> be executed in parallel (parallel blocks and the like).
+
+I also have implemented generics that similarly make it easier to do parallel
+recursion. This allows me to write parallel functions and parallel procedures.
+Syntactic sugar might be able to provide a similar expansion to the parallel
+looping generics. The expansion is somewhat similar, but involves different
+generics.
+
+You have convinced me that it is probably not a good approach to try to unify
+the syntax between sequential iterators and parallel iterators. I am now
+thinking that instead, it would be better to try to unify syntax between
+parallel loops and parallel recursion.
+
+I think that a pragma based approach might work better.
+
+eg. Parallel looping:
+
+ Sum : Integer := 0;
+ for I in 1 .. 100_000_000
+   Sum := Sum + I;
+ end loop;
+ pragma Parallel_Loop (Work_Seeking_Integer_Addition_Reducer, Sum);
+
+In this case, Work_Seeking_Integer_Addition_Reducer is the name of a
+instantiated generic procedure, and Sum is the name of a global variable
+referenced within the loop.
+
+could expand to;
+
+   with Work_Seeking_Integer_Addition_Reducer;
+
+   Sum : Integer := 0;
+
+   declare
+      procedure Iteration
+        (Start               : Integer;
+         Finish              : in out Integer;
+         Others_Seeking_Work : not null access Parallel.Work_Seeking_State;
+         Sum                 : in
+         out Integer) is
+      begin
+         for I in Start .. Finish loop
+            Sum := Sum + I;
+            if Others_Seeking_Work.all then
+               Others_Seeking_Work.all := False;
+               Finish := I;
+               exit;
+            end if;
+         end loop;
+      end Iteration;
+   begin
+      Work_Seeking_Integer_Addition_Reducer
+        (From    => 1,
+         To      => Integer'Value (Command_Line.Argument (2)),
+         Process => Iteration'Access,
+         Item    => Sum);
+   end;
+
+eg. Parallel Recursion:
+
+function Fibonacci (Number : Natural) return Natural is begin
+   if Number < 2 then
+      return Number;
+   else
+      return Fibonacci (Number - 2) + Fibonacci (Number - 1);
+   end if;
+end Fibonacci;
+pragma Parallel_Recursion
+    (Fibonacci, Two_Way_Recursive_Integer_Addition.Parallel_Recursion);
+
+In this case, Fibonacci is the name of the function to be executed in parallel,
+and Two_Way_Recursive_Integer_Addition.Parallel_Recursion is the name of a
+instantiated generic package.
+
+This could expand to the following;
+
+Note that this seems like a fair amount of code, it is mostly a template that
+follows a repeatable pattern. I used this same pattern to create recursive
+parallel iteration through a binary tree. The expansion essentially creates two
+versions of the code. One is the sequential version, which you want to execute
+most of the time, and the second version is the parallel version which gets
+executed when worker tasks become available to do more work. The parallel
+version looks very similar to the sequential version, but instead of calling the
+function recursively, it calls an instantiated function which ultimately causes
+a split in execution between available processors.
+
+with Two_Way_Recursive_Integer_Addition;
+use Two_Way_Recursive_Integer_Addition;
+
+function Fibonacci (Value :
+Natural) return Natural is
+
+   function Parallel_Fibonacci (Number : Natural) return Natural;
+
+   Supervisor : aliased Parallel_Recursion.Overall_Work_Supervisor
+     (Process => Parallel_Fibonacci'Access);
+
+   Others_Seeking_Work : aliased Parallel_Recursion.Work_Seeking_State;
+   use type Parallel_Recursion.Work_Seeking_State;
+
+   function Parallel_Fibonacci (Number : Natural) return Natural is
+   begin
+
+      if Number < 2 then
+         return Number;
+
+      elsif not Others_Seeking_Work then
+
+         return
+           Parallel_Fibonacci (Number - 2) +
+           Parallel_Fibonacci (Number - 1);
+
+      else
+         declare
+            Reduction : aliased Parallel_Recursion.Work_Team_Manager;
+            Sequential_Result : Natural;
+         begin
+
+            Sequential_Result :=
+              Parallel_Recursion.Recurse
+                (Number - 2,
+                 Left,
+                 Reduction'Unchecked_Access,
+                 Supervisor) +
+              Parallel_Recursion.Recurse
+                (Number - 1,
+                 Right,
+                 Reduction'Unchecked_Access,
+                 Supervisor);
+
+            --  Use the parallel result if work was split parallally,
+            --  otherwise use the sequential result
+            return Parallel_Recursion.Result (Reduction, Sequential_Result);
+         end;
+      end if;
+
+   end Parallel_Fibonacci;
+
+   Result : Integer := 0;
+
+begin
+   Parallel_Recursion.Initialize
+     (Supervisor'Unchecked_Access,
+      Others_Seeking_Work'Unchecked_Access);
+
+   Result := Parallel_Fibonacci (Value);
+   Parallel_Recursion.Finalize (Supervisor);
+   return Result;
+end Fibonacci;
+
+The pragmas would cause needed restrictions to be enforced within the parallel
+bodies. If a compiler vendor didn't want to support the parallel expansion, then
+they could ignore the pragma and the code would execute as it does today,
+sequentially.
+
+> Please don't kill this nice sequential proposal by loading up all
+> kinds of parallel cruft on it.
+
+It was definitely not my intent to kill this AI. I was looking to see if it
+could be expanded to cover both parallel and sequential iterators, since it
+seems on the surface that would be a fair bit of common ground between these two
+types of iterators. I see now that these are two vastly different beasts.
+
+I also wanted to minimize the chance that we might paint ourselves into a corner
+with new syntax that might preclude parallel support in the language in the
+future.
+
+I think you have convinced me that this is not a concern here.
+
+The question might be, is there anything that could be done will all this
+parallel cruft I have been rambling on about.
+
+Does it seem like a pragma based approach like I have suggested would be worth
+developing into an AI? Obviously, this is too late for the current amendment. We
+have a lot of AI's to deal with right now and so probably if these ideas have
+enough merit to develop into an AI, they should be more or less shelved until we
+get through the pile of other AI' waiting to be processed. I would certainly be
+willing to work on this in the background though, or at least I hope to create a
+white paper to better explain how these generics work.
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent