CVS difference for ai12s/ai12-0190-1.txt

Differences between 1.4 and version 1.5
Log of other versions for file ai12s/ai12-0190-1.txt

--- ai12s/ai12-0190-1.txt	2016/10/06 04:09:17	1.4
+++ ai12s/ai12-0190-1.txt	2016/12/28 04:20:39	1.5
@@ -1,4 +1,4 @@
-!standard 5.5.2(2/3)                                  16-10-04  AI12-0190-1/02
+!standard 5.5.2(2/3)                                  16-10-12  AI12-0190-1/03
 !class Amendment 16-06-02
 !status work item 16-06-02
 !status received 16-05-06
@@ -30,24 +30,26 @@
 
 !proposal
 
-A lambda_function can be used in a context where the expected type is a single
-access-to-function type (or as the actual parameter for a formal function).
-It is roughly equivalent to using the name'Access (or simply name) of an
-expression function which is declared at the point of use, with parameter
-types, modes, etc. taken from that of the expected access-to-function type
-(or the formal function). Only the formal parameter names come from the
-lambda function.
-
-    primary ::= lambda_function
-
-    lambda_function ::= ( [ lambda_parameter_list ] RETURN expression )
-
-    lambda_parameter_list ::= ( identifier { , identifier } ) | formal_part
-
-We allow only a single expression as the body of the lambda function.  Given
-that we now have "if" expressions and "case" expressions, this is not a
-serious limitation.  (The possible addition of "declare expressions" would
-be a welcome enhancement.)
+A function_expression can be used in a context where the expected type is a
+single access-to-function type (or as the actual parameter for a formal
+function). It is roughly equivalent to using the name'Access (or simply
+name) of an expression function which is declared at the point of use,
+with parameter types, modes, etc. taken from that of the expected
+access-to-function type (or the formal function). Only the formal
+parameter names come from the function_expression.
+
+    primary ::= function_expression
+
+    function_expression ::=
+      ( FUNCTION [ function_formal_parameter_list ] RETURN expression )
+
+    function_formal_parameter_list ::=
+      ( identifier { , identifier } ) | formal_part
+
+We allow only a single expression as the body of the
+function_expression.  Given that we now have "if" expressions and "case"
+expressions, this is not a serious limitation.  (The possible addition
+of "declare expressions" would be a welcome enhancement.)
 
 !wording
 
@@ -55,35 +57,42 @@
 
 !discussion
 
-We are using the reserved word RETURN rather than defining a new reserved word
-such as LAMBDA.  We put it after the (optional) parameter list, immediately
-next to the returned expression, as that is its normal place in the syntax. We
-considered using FUNCTION instead of RETURN, but that left us with potentially
-two parenthesized constructs in a row, which looks somewhat strange (e.g.
-"(function (X) (X**2))").  We could use both FUNCTION and RETURN, as in
-"(function (X) return (X**2))" though that might be considered a bit verbose
-(or maybe not?).
-
-We could call these "return expressions" (although that term would be confusing
-compared to very similar terms used in Return Statements), or we could call
-them "anonymous functions," given that we have dropped the reserved word
-LAMBDA from the syntax.
+We are using the reserved words FUNCTION and RETURN rather than defining
+a new reserved word such as LAMBDA.  We put them surrounding the (optional)
+parameter list, as that is their normal place in the syntax for declaring a
+named function.
+
+We considered other names such as "lambda functions," "function
+literals," and "anonymous functions."  We ultimately went with "function
+expression" as it seemed analogous to "if expression" and "case
+expression," though there is admittedly some discomfort in having both
+"expression functions" and "function expressions."
+
+We allow, but do not require, a full formal part as part of the
+function_expression. Requiring a full formal part seems unnecessary and
+verbose, since the parameter (and result) types are always provided by the
+profile of the formal access-to-function parameter.
 
 We are only supporting defining anonymous functions using this proposed
-construct.  Anonymous procedures are nicely handled with the loop-body proposal
-(AI12-0189).  In any case, mixing statements inside expressions seems like a
-bad idea.
-
-We allow, but do not require, a full formal part as part of the lambda
-function definition. Requiring a full formal part seems unnecessary and
-verbose, since the parameter types are always provided by the profile of
-the formal access-to-function parameter.
+"function_expression" construct.  Anonymous procedures are nicely
+handled with the loop-body proposal (AI12-0189).  In any case, mixing
+statements inside expressions seems like a bad idea.  Also, we don't
+have "expression procedures" so it doesn't seem so bad that we don't
+have "procedure expressions" ;-).
+
+One place where it might be nice to allow a "procedure expression" would
+be when you want to pass in a do-nothing procedure, which is not
+uncommon when instantiating a generic with a formal procedure.  We allow
+using "null" as the default for a formal procedure, as well as when
+defining a null procedure.  It would seem pretty reasonable to allow
+"null" as the actual parameter for a formal procedure, meaning a
+"do-nothing" procedure.
 
 !example
 
     --  Replace control chars with '?'
     Ada.Strings.Fixed.Translate
-      (Str, ((C) return (if C < ' ' then '?' else C)));
+      (Str, (function (C) return (if C < ' ' then '?' else C)));
 
     --  Procedure for plotting a function
     procedure Plot_Graph
@@ -93,16 +102,9 @@
     ...
 
     --  Plot a graph of X-squared from 1 to 20
-    Plot_Graph (Fun => ((Z) return Z**2), Start => 1.0, Stop => 20.0);
-
-Using both "function" and "return" this would be:
-
-    --  Plot a graph of X-squared from 1 to 20
     Plot_Graph (Fun => (function (Z) return Z**2),
                 Start => 1.0, Stop => 20.0);
 
-That doesn't look too bad, and is certainly very clear to the reader.
-
 !ASIS
 
 ** TBD.
@@ -993,5 +995,752 @@
 
 The alternative with both "function" and "return" looks the best to me. The
 others look like something is missing.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October 12, 2016  4:30 PM
+
+Essentially everyone who saw this likes having "function" as part of the syntax.
+So here is an update to the update. [This is version /03 of the AI - Editor.]  I
+also changed the syntax category to be "function_expression" in analogy with
+"if_expression" and "case_expression".
+
+Here is a simple example of the syntax, showing a function_expression that
+returns the square of its operand.
+
+    (function (X) return (X**2))
+
+Types of parameter(s) and result come from the expected profile.
+
+****************************************************************
+
+From: Raphael Amiard
+Sent: Wednesday, October 12, 2016  4:46 PM
+
+I'm confused about something though. I will have to look at the minutes, but
+from what I remember from the last meeting, the general agreement was that:
+
+- In most languages lambdas/anonymous functions imply closures
+- Making them equivalent to nested functions only gave a negligible boost in
+  expressivity and readability.
+- But on the other hand would be confusing to people expecting them to work like
+  *real* anonymous functions in other languages
+
+So in the end my understanding was that we should investigate the closure
+behavior, and that if not it was not deemed a worthy addition to the language.
+
+I don't see any mention of that in the AI, on the contrary it does exactly what
+we agreed was not worth it.
+
+Did I miss something ?
+
+****************************************************************
+
+From: Raphael Amiard
+Sent: Wednesday, October 12, 2016  4:49 PM
+
+I did not miss something. Here is the relevant extract:
+
+
+Erhard says that a simple version isn't interesting. People he knows are only
+interested in being able to return constructed lambdas. Steve wonders if
+supporting a syntax sugar only version would do more harm than good. People
+would think that we are just faking. Erhard thinks we could try to make this
+safe by the right restrictions, that would be a boon. (C++ just crashes if one
+does.)
+Keep alive (original version): 2-4-6.
+Keep alive (complex version): 6-1-5. (A complex version would support some sort
+of constructed lambda.) Tucker will take another shot at this. Florian would
+like to help.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October 12, 2016  5:50 PM
+
+> I did not miss something. Here is the relevant extract:
+
+Good point.  I missed/forgot that.  On the other hand, if we can at least agree
+on the syntax, we could then look into the semantics. ;-)
+
+It seems what is being requested is the ability to write something like this:
+
+    function Filter(Pattern : String) return access function (X : String) return Boolean;
+
+This will return a filter which returns True only if X matches the pattern.
+
+Trying to write this:
+
+     function Filter(Pattern : String)
+       return access function (X : String) return Boolean is
+     begin
+         return (function (X) return Match(X, Pattern));
+     end Filter;
+
+This is do-able by treating such a result as living on the secondary stack, I
+suppose, which we would *not* cut back until the returned function is no longer
+being used.
+
+So it seems that the proposed syntax could work, provided we defined the
+semantics of returning an access-function as having this possibility of
+preserving the context on the secondary stack.
+
+Personally, I am not convinced that this added functionality is that important,
+but others seem to think that without it the feature is useless.  If there is
+interest, for the next ARG meeting I could add more details about the
+implementation requirements associated with this added functionality, presuming
+I have captured it correctly.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, October 12, 2016  6:01 PM
+
+It gets more interesting ("interesting" sounds better than "preposterously
+inappropriate for Ada") if the anonymous function can refer to things declared
+inside of Filter, so that they have to persist after Filter returns.
+
+Even if these guys are pretty much just syntactic sugar, we need to be a little
+bit careful in defining them via an equivalence rule because they can refer to
+the implicitly declared object of a quantified_expression or of an
+iterated_component_association.
+
+Since that cannot be done with an explicitly declared function, a simple
+equivalence rule breaks down in this case.
+
+Consider the following (admittedly contrived) example
+
+    function Foo (Func : access function return Character) return Boolean
+      is ... ;
+
+    Flag : Boolean := (for some C in Character =>
+                         Foo (Func => (function return (C))));
+
+This is not a fundamental problem - just a case that we would need to confirm is
+defined correctly.
+
+[Randy - yes, I mentioned this one to you a while back.]
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, October 12, 2016  8:07 PM
+
+> ...
+> It gets more interesting ("interesting" sounds better than
+> "preposterously inappropriate for Ada") if the anonymous function can
+> refer to things declared inside of Filter, so that they have to
+> persist after Filter returns.
+
+Yes, I was presuming the entire stack frame of Filter would be preserved on the
+secondary stack, so you could refer to anything visible at the point of the
+function return.  This seems implementable.  You just have to put all things
+that are referenced (directly or indirectly) by the return statement on the
+secondary stack rather than the primary stack. For simplicity, you could just
+allocate everything local to Filter on the secondary stack.
+
+>
+> Even if these guys are pretty much just syntactic sugar, we need to be
+> a little bit careful in defining them via an equivalence rule because
+> they can refer to the implicitly declared object of a
+> quantified_expression or of an iterated_component_association.
+>
+> Since that cannot be done with an explicitly declared function, a
+> simple equivalence rule breaks down in this case.
+>
+> Consider the following (admittedly contrived) example
+>
+>    function Foo (Func : access function return Character) return Boolean
+>      is ... ;
+>
+>    Flag : Boolean := (for some C in Character =>
+>                         Foo (Func => (function return (C))));
+>
+> This is not a fundamental problem - just a case that we would need to
+> confirm is defined correctly.
+
+Agreed.  I don't see any strong reason to define these by an equivalence rule.
+I was using the equivalence more to help understand the limitation to a single
+expression, which is similar to an expression function.
+
+One twist that I considered for ParaSail was, when the formal was of a
+parameterless function type, the caller would be allowed to pass a simple
+expression of the return type as the actual parameter (rather than a lambda).
+You could then (in ParaSail syntax) define a short-circuit operation like "and
+then" as:
+
+    op "and then"(Left : Boolean; Right : func() -> Boolean) -> Boolean is
+       if Left then
+          return Right();
+            //  evaluate the right-hand operand only if necessary
+       else
+          return #false;
+       end if;
+    end op "and then";
+
+This doesn't work quite as well when the parameter type is necessarily an
+access-to-function type as in Ada, since the actual parameter for Right might be
+overloaded so that it could legally be interpreted as either of the correct
+access-function type, or of the access-function's result type.  It would be
+upward incompatible to consider that ambiguous, though being able to gain the
+feature of unevaluated parameters might be worth it!
+
+****************************************************************
+
+From: Steve Baird
+Sent: Wednesday, October 12, 2016  10:44 PM
+
+> This seems implementable.
+
+True, but at some cost in complexity.
+
+en.wikipedia.org/wiki/Parent_pointer_tree says:
+
+   The term spaghetti stack is closely associated with implementations
+   of programming languages that support continuations. Spaghetti stacks
+   are used to implement the actual run-time stack containing variable
+   bindings and other environmental features. When continuations must be
+   supported, a function's local variables cannot be destroyed when that
+   function returns: a saved continuation may later re-enter into that
+   function, and will expect not only the variables there to be intact,
+   but it will also expect the entire stack to be present so the
+   function is able to return again. To resolve this problem, stack
+   frames can be dynamically allocated in a spaghetti stack structure,
+   and simply left behind to be garbage collected when no continuations
+   refer to them any longer. This type of structure also solves both the
+   upward and downward funarg problems, so first-class lexical closures
+   are readily implemented in that substrate also.
+
+   Examples of languages that use spaghetti stacks are:
+
+     Languages having first-class continuations such as Scheme
+        and Standard ML of New Jersey
+     Languages where the execution stack can be inspected and
+        modified at runtime such as Smalltalk
+     Felix
+     Cilk
+
+The interactions with tasking, masters, and finalization would also need to be
+worked out.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 13, 2016  7:42 AM
+
+>   The term spaghetti stack is closely associated with implementations
+>   of programming languages that support continuations. ...
+
+I am not sure we need support for full continuations to support returning
+function expressions.  If we allocate everything of interest on the secondary
+stack and then return the access-to-function without cutting it back (and
+without performing any finalization), what more do we need to do?  I have
+presumed the accessibility checks would treat this roughly the same way we treat
+access-to-subprogram parameters, as though the accessibility level is deeper
+than any master, so you can't convert it to any named access-to-subprogram type.
+All you can do is pass the result of a call to an access-to-subprogram
+parameter, or return the result of the call.  With these restrictions, you
+cannot create arrays of these function expressions, nor store them in any object
+of a named access type.
+
+In any case, I agree that none of this is trivial.  Also, looking at other
+languages that support lambda expressions, many of them support only passing
+them as parameters, so I don't think Ada would be in such a bad situation if we
+started out only supporting them as parameters, and consider support for
+returning them as a later extension.
+
+****************************************************************
+
+From: Raphael Amiard
+Sent: Thursday, October 13, 2016  10:23 AM
+
+> Good point.  I missed/forgot that.  On the other hand, if we can at least
+> agree on the syntax, we could then look into the semantics. ;-)
+
+Fine by me ! I guessed that this was an omission :)
+
+> It seems what is being requested is the ability to write something like this:
+>
+>   function Filter(Pattern : String) return access function (X : String) return Boolean;
+>
+>This will return a filter which returns True only if X matches the pattern.
+
+This is one of the things that you could do indeed.
+
+>Trying to write this:
+>
+>    function Filter(Pattern : String)
+>      return access function (X : String) return Boolean is
+>    begin
+>        return (function (X) return Match(X, Pattern));
+>    end Filter;
+
+Yeah that's a good example, because we can see that the lambda-function captures
+the Pattern parameter.
+
+> This is do-able by treating such a result as living on the secondary stack,
+> I suppose, which we would *not* cut back until the returned function is no
+> longer being used.
+>
+> So it seems that the proposed syntax could work,
+
+I like the syntax very much indeed ! This is akin to what Javascript/Lua/ML do.
+
+> provided we defined the semantics of returning an access-function as having
+> this possibility of preserving the context on the secondary stack.
+
+This is not sufficient. Suppose you want to then store the resulting filter
+lambda function, for example to use in your *lazy* iterator (that could be
+implemented using a generator ^^, or not), that will call it everytime the users
+calls "Next" on it.
+
+> Personally, I am not convinced that this added functionality is that
+> important, but others seem to think that without it the feature is useless.
+> If there is interest, for the next ARG meeting I could add more details
+> about the implementation requirements associated with this added
+> functionality, presuming I have captured it correctly.
+
+Well, I disagree. I think it's important if you want to program in a certain
+style. It makes certain patterns much more expressive. One example is the
+previous example of providing filters to iterators:
+
+for Node of Tree.Search(function (N): N.Kind = Function_Call) loop
+    Do_Stuff;
+end loop;
+
+If search is done in such a way that it returns an iterator object (which it
+should, because you might want to abort the search before the end), then it will
+need to take ownership of the lambda, or store a reference to it (depending on
+the semantics of the lambda objects).
+
+Another very common example is giving event handlers in event oriented
+programming:
+
+procedure Build_GUI is
+    My_Button  : Button;
+    My_Form    : Form;
+begin
+    Initialize_Payment_Form (My_Form);
+    Button.Set_On_Click (function (B): My_Form.Show);
+end Build_GUI;
+
+Of course, here, to be correct, the Form type needs to be some kind of
+ref-counted type. That's fine.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 13, 2016  11:21 AM
+
+> ...
+>> So it seems that the proposed syntax could work,
+>
+> I like the syntax very much indeed ! This is akin to what Javascript/Lua/ML
+> do.
+>
+>> provided we defined the semantics of returning an access-function as
+>> having this possibility of preserving the context on the secondary stack.
+>
+> This is not sufficient. Suppose you want to then store the resulting
+> filter lambda function, for example to use in your *lazy* iterator
+> (that could be implemented using a generator ^^, or not), that will call it
+> everytime the users calls "Next" on it.
+
+I am not convinced we need to store these, so I would have to see the problem we
+are trying to solve.  I am sure you could construct an example that could take
+advantage of storing them, but I would suspect (hope?) that there are other ways
+of accomplishing the same thing without doing so.  I am not a big fan of burying
+everything in lambdas (as explained a bit more below).
+
+>> Personally, I am not convinced that this added functionality is that
+>> important, but others seem to think that without it the feature is
+>> useless.  If there is interest, for the next ARG meeting I could add
+>> more details about the implementation requirements associated with this added
+>> functionality, presuming I have captured it correctly.
+>
+> Well, I disagree. I think it's important if you want to program in a
+> certain style. It makes certain patterns much more expressive. One
+> example is the previous example of providing filters to iterators:
+>
+>     for Node of Tree.Search(function (N): N.Kind = Function_Call) loop
+>         Do_Stuff;
+>     end loop;
+>
+>
+> If search is done in such a way that it returns an iterator object
+> (which it should, because you might want to abort the search before
+> the end), then it will need to take ownership of the lambda, or store
+> a reference to it (depending on the semantics of the lambda objects).
+>
+> Another very common example is giving event handlers in event oriented
+> programming:
+
+I think perhaps you are trying to make lambdas solve all problems, when in fact
+event handlers are quite naturally represented as objects with their dispatching
+operations being the call backs.  There are some languages where all you have
+are lambda expressions, and you end up using them for everything.  But for
+languages that have support for dynamic dispatch already, the need for function
+objects is much reduced in my view, and generalizing them too much is just
+adding complexity and redundancy to the language definition.
+
+In Java, I believe these might end up just being syntactic sugar around
+declaring a new class with a single operation.  We could go in that direction
+for Ada if we think it is important to be able to store these things, but I
+think that is yet another step that seems even less important than being able to
+return them.
+
+I think you also have to think about the debugging problem.  You are effectively
+creating large numbers of partial stack contexts, each of which is a potentially
+very complex piece of state.  Trying to debug such a situation is much harder
+than debugging a more data-object-based world, where the contents of the fields
+of a record, or equivalent, represents the current state of things.  Yes it is
+kind of cool that you can do all kinds of amazing things with lambdas, but I am
+not convinced that is the clearest, most efficient, and most verifiable way to
+solve the problem.  We should be really sure we need to add all of this
+complexity on top of all the features already available for solving such
+problems.
+
+****************************************************************
+
+From: Raphael Amiard
+Sent: Thursday, October 13, 2016  1:21 PM
+
+> I am not convinced we need to store these, so I would have to see the
+> problem we are trying to solve.  I am sure you could construct an
+> example that could take advantage of storing them, but I would suspect
+> (hope?) that there are other ways of accomplishing the same thing
+> without doing so.  I am not a big fan of burying everything in lambdas (as
+> explained a bit more below).
+
+Well, the problem is that you are then inventing a feature called lambda
+functions that behaves slightly differently from the way it behaves in *every*
+other languages that has lambda functions, because of implementation
+considerations. I think the full version is implementable.
+
+By the way, the event handler thing is a perfect example of why you would want
+to store a closure object. It's a feature that has been asked many times by
+users of GtkAda, both inside and outside of AdaCore.
+
+> I think perhaps you are trying to make lambdas solve all problems,
+> when in fact event handlers are quite naturally represented as objects
+> with their dispatching operations being the call backs.  There are
+> some languages where all you have are lambda expressions, and you end up
+> using them for everything.
+
+There are no such languages in wide use today, when even Scheme has a
+standardized object system. However, there are a ton of languages (Python,
+Javascript, OCaml, Scala, C++) where you could use one or the other, but where
+people *consistently choose* to use lambda functions to do that kind of thing in
+a certain subset of cases, because they are a much more expressive way of doing
+the same thing, where all you can see as the reader of the code is the part of
+the code that expresses the intent of the programmer.
+
+>   But for languages that have support for dynamic dispatch already,
+> the need for function objects is much reduced in my view, and
+> generalizing them too much is just adding complexity and redundancy to the
+> language definition.
+
+Well, the fact that they added lambda functions to Java, and that they are
+closures, is a good counter-argument to this. They could already do everything
+with objects, but still decided to add lambdas. It does not mean we should add
+them. However, in my view, it sure means that if we add them they should behave
+consistently with user expectations however.
+
+> In Java, I believe these might end up just being syntactic sugar
+> around declaring a new class with a single operation.  We could go in
+> that direction for Ada if we think it is important to be able to store
+> these things, but I think that is yet another step that seems even
+> less important than being able to return them.
+
+Yes, in Java they implemented them as anonymous classes, which are closures, and
+hence respect the expectations of the users regarding lambdas.
+
+> I think you also have to think about the debugging problem.  You are
+> effectively creating large numbers of partial stack contexts, each of
+> which is a potentially very complex piece of state. Trying to debug
+> such a situation is much harder than debugging a more
+> data-object-based world, where the contents of the fields of a record,
+> or equivalent, represents the current state of things. Yes it is kind
+> of cool that you can do all kinds of amazing things with lambdas, but
+> I am not convinced that is the clearest, most efficient, and most
+> verifiable way to solve the problem.  We should be really sure we need
+> to add all of this complexity on top of all the features already available for
+> solving such problems.
+
+That's a good point, but there are solutions to that that already exist. The
+call to the lambda expression will appear in the context it is declared, where
+you can naturally refer to the variables it closes over.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 13, 2016  2:03 PM
+
+>> I am not convinced we need to store these, so I would have to see the
+>> problem we are trying to solve.  I am sure you could construct an
+>> example that could take advantage of storing them, but I would
+>> suspect (hope?) that there are other ways of accomplishing the same
+>> thing without doing so.  I am not a big fan of burying everything in
+>> lambdas (as explained a bit more below).
+>
+> Well, the problem is that you are then inventing a feature called
+> lambda functions that behaves slightly differently from the way it
+> behaves in *every* other languages that has lambda functions, because
+> of implementation considerations. I think the full version is implementable.
+
+I think you need to distinguish between garbage-collected languages where
+everything of interest lives on the heap and has an indefinite lifetime, from
+languages that attempt to keep most objects on a stack.  In C++11 they say you
+are on your own from a safety point of view if you capture a "reference" to a
+local variable.  So clearly there are more limitations when objects might be
+stack based, or can't be copied.  Also, as you start expecting the compiler to
+"do the right thing" and either complain or somehow automatically copy data that
+is referenced, implementation expense goes up and the complexity of the
+limitations from the user's perspective also grows.
+
+I think a basic limitation such as treating these like objects of a limited type
+that you can temporarily give a name either via rename or a build-in-place
+declaration, but that you can't store in some global variable, might be
+reasonable and would cover 90% of the cases of interest, without opening
+ourselves up to the complexity of a C++-like solution.
+
+> By the way, the event handler thing is a perfect example of why you
+> would want to store a closure object. It's a feature that has been
+> asked many times by users of GtkAda, both inside and outside of AdaCore. ...
+
+I wonder whether some good syntactic sugar could make this work using tagged
+types and single-operation interfaces.  This is not a case where you need to
+construct the event handler dynamically and/or return it from a function.  You
+just want an easy way to describe what happens when the event occurs, without
+the heavy syntax burden of defining a new type with a new operation, and then
+adding an appropriately initialized object of that type onto a list.
+
+Another option I suppose might be to support something like an event channel.
+You put your event channel on one or more lists, and then read from the channel
+and write a simple "case" statement to handle the events as they arrive.
+
+****************************************************************
+
+From: Raphael Amiard
+Sent: Thursday, October 13, 2016  2:28 PM
+
+>> Well, the problem is that you are then inventing a feature called
+>> lambda functions that behaves slightly differently from the way it
+>> behaves in *every* other languages that has lambda functions, because
+>> of implementation considerations. I think the full version is
+>> implementable.
+>
+> I think you need to distinguish between garbage-collected languages
+> where everything of interest lives on the heap and has an indefinite
+> lifetime, from languages that attempt to keep most objects on a stack.
+> In C++11 they say you are on your own from a safety point of view if
+> you capture a "reference" to a local variable.
+
+Yes, but you can still capture a value, so it makes all the relevant cases that
+I talked about possible in C++11. For capturing references you use
+smart-pointers, which are captured by value, but the value of a smart-pointer is
+really a reference so all is well.
+
+>   So clearly there are more limitations when objects might be stack
+> based, or can't be copied.  Also, as you start expecting the compiler
+> to "do the right thing" and either complain or somehow automatically
+> copy data that is referenced, implementation expense goes up and the
+> complexity of the limitations from the user's perspective also grows.
+
+No, this is the way that it is supposed to work (capture by value). You have an
+option for capture by reference in C++ but byval is always used in practice. If
+you want reference semantics you use a smart-pointer.
+
+> I think a basic limitation such as treating these like objects of a limited
+> type that you can temporarily give a name either via rename or a
+> build-in-place declaration, but that you can't store in some global variable,
+> might be reasonable and would cover 90% of the cases of interest, without
+> opening ourselves up to the complexity of a C++-like solution.
+
+You can put an object of limited type in a global access variable, by allocating
+the object dynamically. If we have such an option for lambdas, and make them
+limited, then I'm 100% fine with that solution.
+
+I think referencing outer variable needs to be treated like if those were
+implicit
+
+>>
+>> By the way, the event handler thing is a perfect example of why you would
+>> want to store a closure object. It's a feature that has been asked many times
+>> by users of GtkAda, both inside and outside of AdaCore. ...
+>
+> I wonder whether some good syntactic sugar could make this work using tagged
+> types and single-operation interfaces.
+
+It could but raises several problems:
+
+1. In C++ the equivalence works because you can overload the call operator. We
+could provide something similar I guess, via an aspect for example.
+2. The type of your closure, instead of being a special built-in access to
+function type, then becomes a variadic generic function type. We don't have
+variadic generics, and we'd still have to instantiate and name specific generic
+for every closure instance, which is a pain.
+
+Meta-point: This is IMHO the third time that it turns out that we have
+weaknesses in the generic model that would force us to have built-in solutions
+instead of hybrid library ones, or completely library ones:
+
+1. The first is the type of generators.
+2. The second is the type of lambda functions.
+3. The third is the 'Reduce function/built-in.
+
+>   This is not a case where you need to construct the event handler dynamically
+> and/or return it from a function.  You just want an easy way to describe what
+> happens when the event occurs, without the heavy syntax burden of defining a
+> new type with a new operation, and then adding an appropriately initialized
+> object of that type onto a list.
+
+Well yeah indeed, but what you're doing is essentially a custom version of the
+general lambda mechanism: Capturing the necessary variables, wrapping that in an
+object with a call, and returning it as a function.
+
+****************************************************************
+
+From: Erhard Ploedereder
+Sent: Thursday, October 13, 2016  11:20 AM
+
+> It seems what is being requested is the ability to write something
+> like
+> this:
+>    function Filter(Pattern : String) return access function (X :
+> String) return Boolean; This will return a filter which returns True
+> only if X matches the pattern.
+
+Indeed. Coincidentally, when Java came up with lambdas, this capability of
+composing and returning functions, or using currying strategies to obtain
+partially instantiated functions was THE major feature that at least one of our
+industrial customer was heavily interested in. (I had a student doing a thesis
+on Java lambdas for this customer - unfortunately not a good one.) And I see
+what my functionally inclined grad students produce: heavy use of this
+capability.
+
+> Trying to write this:
+>
+>     function Filter(Pattern : String)
+>       return access function (X : String) return Boolean is
+>     begin
+>         return (function (X) return Match(X, Pattern));
+>     end Filter;
+>
+> This is do-able by treating such a result as living on the secondary
+> stack, I suppose, which we would *not* cut back until the returned
+> function is no longer being used.
+
+Well, or have lambdas carry closures, i. e., a record of all values of free
+variables at the time of lambda creation. Admittedly, this differs from Ada,
+where up-level variables are referenced, not locally copied, but this is how
+assignment-less functional languages operate. And, having references to anything
+not global in a closure should be an accessibility violation - no exceptions.
+
+Secondary stacks for all lambda creators in their textual region? Surely an
+unbearable cost, especially when folks really get into recursive functional
+programming.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Thursday, October 13, 2016  11:48 AM
+
+>> This is do-able by treating such a result as living on the secondary
+>> stack, I suppose, which we would *not* cut back until the returned
+>> function is no longer being used.
+>
+> Well, or have lambdas carry closures, i. e., a record of all values of
+> free variables at the time of lambda creation. Admittedly, this
+> differs from Ada, where up-level variables are referenced, not locally
+> copied, but this is how assignment-less functional languages operate.
+
+Particularly challenging when dealing with objects of a limited type.
+
+> ... And,
+> having references to anything not global in a closure should be an
+> accessibility violation - no exceptions.
+
+OK, so you are saying you cannot refer to local variables, only parameters and
+globals, in a returned function expression?  Seems pretty limiting.  Basically
+you have to put all of the computation inside the function expression itself,
+which seems kind of unpleasant, especially if you have some computations you
+could do once in advance, since they are independent of the parameters passed to
+the function expression.
+
+If we go that route, we should probably impose the same limitations as used by
+access discriminants, requiring the use of "aliased" parameters if referring to
+[in] out parameters, presuming that we are capturing the 'Access of all free
+variables that we are not copying.  That is, we would have a block of 'Access
+values for such free variables that was part of the representation of such a
+function expression.
+
+> Secondary stacks for all lambda creators in their textual region?
+> Surely an unbearable cost, especially when folks really get into
+> recursive functional programming.
+
+It seems you could optimize by storing on the secondary stack only those things
+that are actually referenced (directly or indirectly) in the returned function
+expression.  I suggested, for simplicity, that you could put everything on the
+secondary stack, but clearly you can do better than that.
+
+****************************************************************
+
+From: Erhard Ploedereder
+Sent: Thursday, October 13, 2016  2:48 PM
+
+>> ... And,
+>> having references to anything not global in a closure should be an
+>> accessibility violation - no exceptions.
+>
+> OK, so you are saying you cannot refer to local variables, only
+> parameters and globals, in a returned function expression?
+
+No, you can of course refer to uplevel variables, but what you get is the value
+that this entity held when the lambda was created. You do not get an opportunity
+to assign to the original, because all you hold is a copy. If you assign (if
+permitted at all??), then you change the copy.
+
+Absent assignments, this semantics is indistinguishable from the Ada semantics
+of uplevel addressing. With assignments to the up-level address inside or
+outside, the semantics obviously differ.
+
+Put differently, up-level variables are effectively cached locally, and that is
+the semantics of the new feature called lambdas.
+
+The accessibility issue arises when said value is in turn a reference, e.g. the
+code refers to an up-level variable of access type, which in turn references
+something. The reference value copied from the local variable better be to a
+global entity, nothing else. (One could refine this, but the rules will be as
+inscrutable as today's accessibility rules.)
+
+****************************************************************
+
+From: Erhard Ploedereder
+Sent: Thursday, October 13, 2016  4:23 PM
+
+>>     function Filter(Pattern : String)
+>>       return access function (X : String) return Boolean is
+>>     begin
+>>         return (function (X) return Match(X, Pattern));
+>>     end Filter;
+
+more on Syntax (and Semantics): I am not so sure that I like the lambda to be
+returned typed as an access function ...., implying that it can be assigned to
+some variables, hooked into dispatch vectors, etc.
+
+I would much prefer an ability to name, but not necessarily to assign these
+values. E.g.,
+
+     function Filter(Pattern : String)
+       return function (X : String) return Boolean is
+     begin
+         return (function (X) return Match(X, Pattern));
+     end Filter;
+
+and if anybody wants a name for the lambda:
+
+function ParisMatch(X : String) return Boolean is Filter("Paris");
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent