<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<style type="text/css">

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

</style>

<title>Lambda syntax should be more liberal in what it accepts</title>
</head>
<body>

<b>Document number:</b> P0756R0 <br>
<b>Date:</b> 2017-08-12 <br>
<b>Project:</b> ISO JTC1/SC22/WG21, Programming Language C++ <br>
<b>Audience:</b> Evolution Working Group <br>
<b>Reply to:</b> Arthur O'Dwyer &lt;arthur.j.odwyer@gmail.com&gt; <br>

<h1>Lambda syntax should be more liberal in what it accepts</h1>

<p>
<a href="#Introduction">1. Introduction</a><br>
<a href="#Motivations">2. Motivations</a><br>
<a href="#Simple">3. "Simple. The default goes first."</a><br>
<a href="#Proposed_wording">4. Proposed wording</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#expr.prim.lambda">8.1.5.2 Captures [expr.prim.lambda.capture]</a><br>
<a href="#References">5. References</a><br>
</p>


<h2><a name="Introduction">1. Introduction</a></h2>

<p>
This paper proposes to remove two minor stumbling blocks to the teachability
of lambda syntax &mdash; stumbling blocks of which many programmers may not even be aware.<br>
The first is that <code>[&x, =](){ return x; }</code> is ill-formed.<br>
The second is that <code>[=, y](){ return x; }</code> is ill-formed.<br>
I propose to make both of these lambdas well-formed, with the obvious meanings.
</p>

<p>
This proposal is effectively a superset of Thomas Köppe's recent proposal
"Allow lambda capture <code>[=, this]</code>" <a href="#P0409R2">[P0409R2]</a>;
the difference is that P0409 proposes to add a single word to [expr.prim.lambda.capture]
whereas this paper proposes to strike the entire offending <i>sentence</i> from that clause.
</p>

<h2><a name="Motivations">2. Motivations</a></h2>

<p>Here is an excerpt from a tutorial I have been writing on lambdas in C++17:</p>
<blockquote>
<p>
One of the ways in which lambda-expressions add expressive power to the language
(that is, one way in which they're more than just syntactic sugar for the C++03
equivalents that we've been showing so far in this chapter) is that you can take
the tedious work of counting the captures you need, and foist that work off on
the compiler.
To capture "everything needed by this lambda, and nothing else," simply add a
single <code>=</code> to your capture-list (to capture by value), or add a single
<code>&amp;</code> (to capture by reference).
</p>
<p>
This "capture-default" syntax can be prepended onto the other syntaxes
previously discussed, so that for example <code>[=, p=q, &amp;r]</code> means <i>"my
data member <code>p</code> should be initialized to a copy of <code>q</code> from the
enclosing scope; my data member <code>r</code> should be a reference to the <code>r</code>
in the enclosing scope; and anything else I need should be captured by value."</i>
</p>
<p>
Unfortunately, the syntax is not as forgiving as you might expect; for example
placing the <code>=</code> at the end of the list (where it logically belongs) is a
syntax error, and "redundant" C++11-style captures are not allowed &mdash; for
example <code>[=, x]</code> is forbidden but <code>[=, x=x]</code> is permitted.
</p>
</blockquote>

<p>The final paragraph above is unfortunate. It would be easier to teach C++,
and less verbiage would be expended on syntactic trivia, if we loosened
up the arbitrary requirements above.</p>

<p>Another motivation for loosening the prohibition against "redundant" captures
is to improve our friendliness to machine-generated or mechanically-refactored code.
The default capture modes (such as <code>[=]</code>) are useful in allowing us to
write lambdas without manually counting the variables that need capturing. But
if we have in mind one particular variable that <i>does</i> need capturing, regardless
of what other variables are odr-used within the body of the lambda, it would be
convenient to be able to specify it directly as a C++11-style capture. For example:</p>

<pre>
    struct TokenPool : std::enable_shared_from_this&lt;TokenPool> {
        TokenPool(int initial_number_of_tokens);
        std::shared_ptr&lt;bool> get() {
            auto shared_this = shared_from_this();
            bool *p;
            // ... block until some "p" is available, then remove it from the pool ...
            return std::shared_ptr&lt;bool>(p, [shared_this](bool *p){
                shared_from_this->putback(p);
            });
        }
      private:
        void putback(bool *p) {
            // ... put "p" back in the pool ...
        }
    };
    TokenPool token_pool(100);

    struct Task : std::enable_shared_from_this&lt;Task> {
        void run();
    };

    void Task::run()
    {
        auto shared_this = shared_from_this();
        auto token = token_pool.get();  // block; don't launch our new thread until there's a token available for us
        for (int i=0; i < 100; ++i) {
            worker_pool.launch(<b>[token, shared_this, i](){
                shared_this->execute_one_shard_of_task(i);
            }</b>);
            // We'll hold onto that token until every one of these lambdas has finished running.
            // Then the token will put itself back in the pool.
        }
    }
</pre>

<p>
The important piece of the above code sample is the lambda-expression whose lambda-capture is
<code>[token, shared_this, i]</code>.
Under the current standard, this is as far as we can simplify the code using
just C++11-style captures. An alternative way to write it is
<code>[=, token=token](){ ... }</code>, but that awkwardly duplicates the
name of identifier <code>token</code>. (We could pick a shorter name for the left-hand
side of that assignment — for example <code>[=, x=token]</code> — but then we'd have to
verify manually that there was no use of any existing <code>x</code> inside the lambda's body.)
</p>

<p>
Under this proposal, the syntaxes <code>[=, token]</code> and <code>[token, =]</code>
would both be supported for the above example's capture-list.
</p>

<h2><a name="Simple">3. "Simple. The default goes first."</a></h2>

<p>
In discussion on the std-proposals mailing list <a href="#Bolas">[Bolas]</a>, the following objection was raised:
<blockquote>
    Seeing `=` first makes it clear to the reader that this is a value default-capturing lambda.
    Seeing `&` first makes it clear that it's a reference default-capturing lambda.
    Seeing neither makes it clear that it captures only what is listed.
    It's a simple rule to remember: <i><b>put the default first</b></i>. I don't think that rule affects teachability.
    [...]
    Unless you think that "default initialization" is somehow related to and should be
    syntactically consistent with "default parameters" or "default capture".
</blockquote>
</p>

<p>My rebuttal is that currently C++ supports "defaults" or "default behavior" in the following
places associated with the <i>trailing end</i>:
<ul>
<li>Default values for function arguments (such arguments can appear only at the <i>end</i>)</li>
<li>C-style variadic "..." soaks up unmatched arguments (only at the <i>end</i>)</li>
<li>Variadic template parameter packs soak up unmatched arguments (technically anywhere but
typically you find them at the <i>end</i>)</li>
<li>Aggregate initializer "set the rest of my fields to zero" (only for <i>trailing</i> fields)</li>
</ul>
And in the following places, "default behaviors" can appear in any order, intermixed with non-defaults:
<ul>
<li>Default values for template parameters</li>
<li>Default values for non-static data members</li>
</ul>
In only this one place does the "default behavior" for a C++ construct appear at the <i>beginning</i>
of a construct:
<ul>
<li>Default capturing behavior for lambda expressions (only at the <i>beginning</i>)</li>
</ul>
The simple rule <i>put the default first</i> is not a rule that appears anywhere else in C++; while many
places in C++ encourage the student to learn the competing rule, <i><b>put the default last</b></i>.
</p>

<p>
Normal English usage is also on the side of "default last": it feels natural to say
<blockquote>
    <i>Put the apple in the basket, the banana in the bowl, and everything else in the cupboard.</i>
</blockquote>
It feels <i>un</i>natural to say
<blockquote>
    <i>Put everything else in the cupboard, the apple in the basket, and the banana in the bowl.</i>
</blockquote>
Yet the latter is what C++11 lambda syntax requires from the student!
</p>

<p>
This is not intended to convince you that the "right" place for the capture-default is in the trailing
position. This is merely intended to convince you that many students naturally <i>try</i> (and even
<i>want</i>) to put the default in the trailing position, and get frustrating compiler errors as a result.
Here are the compiler error messages from GCC, Clang, and Visual C++ as of this writing:
<pre>
    (GCC 8.0.0)
    prog.cc: In function 'int main()':
    prog.cc:9:9: error: expected identifier before '=' token
         [x, =]() { };
             ^

    (Clang 6.0.0)
    prog.cc:9:9: error: expected variable name or 'this' in lambda capture list
        [x, =]() { };
            ^

    (Visual C++ 19.00.23506)
    source_file.cpp(9): error C2337: 'x': attribute not found
    source_file.cpp(9): error C2059: syntax error: '='
    source_file.cpp(9): error C2143: syntax error: missing ';' before '{'
</pre>
Just changing all the major compilers to produce better error messages would be an improvement
on the status quo. But even better would be to make the code compile on the first shot!
</p>


<h2><a name="Proposed_wording">4. Proposed wording for C++20</a></h2>

<p>
The wording in this section is relative to WG21 draft N4659 <a href="#N4659">[N4659]</a>,
that is, the current draft of the C++17 standard as of July 2017.
</p>

<h3><a name="expr.prim.lambda">8.1.5.2 Captures [expr.prim.lambda.capture]</a></h3>

<p>
Edit the grammar in paragraph 1 as follows.
</p>

<blockquote class="std">
<p>
<i>lambda-capture:<br>
&nbsp;&nbsp;&nbsp;&nbsp;<del>capture-default</del><br>
&nbsp;&nbsp;&nbsp;&nbsp;capture-list</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<del><i>capture-default</i> <code>,</code> <i>capture-list</i></del><br>
<i>capture-default:</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>&amp;</code><br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>=</code><br>
<i>capture-list:</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<ins><i>capture-default</i></ins><br>
&nbsp;&nbsp;&nbsp;&nbsp;<ins><i>capture-list</i> <code>,</code> <i>capture-default</i></ins><br>
&nbsp;&nbsp;&nbsp;&nbsp;<i>capture</i> <code>...</code><i><sub>opt</sub></i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<i>capture-list</i> <code>,</code> <i>capture</i> <code>...</code><i><sub>opt</sub></i><br>
<i>capture:<br>
&nbsp;&nbsp;&nbsp;&nbsp;simple-capture<br>
&nbsp;&nbsp;&nbsp;&nbsp;init-capture<br>
simple-capture:<br>
&nbsp;&nbsp;&nbsp;&nbsp;identifier</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>&</code> <i>identifier</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>this</code><br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>* this</code><br>
<i>init-capture:<br>
&nbsp;&nbsp;&nbsp;&nbsp;identifier initializer</i><br>
&nbsp;&nbsp;&nbsp;&nbsp;<code>&amp;</code> <i>identifier initializer</i><br>
</p>
</blockquote>

<p>
Edit paragraph 2 as follows.
</p>

<blockquote class="std">
<p>
    <del>If a <i>lambda-capture</i> includes a <i>capture-default</i> that is <code>&amp;</code>,
    no identifier in a <i>simple-capture</i> of that <i>lambda-capture</i> shall be preceded by
    <code>&amp;</code>.
    If a <i>lambda-capture</i> includes a <i>capture-default</i> that is <code>=</code>, each
    <i>simple-capture</i> of that <i>lambda-capture</i> shall be of the form
    “<code>&amp;</code> <i>identifier</i>” or “<code>* this</code>”.
    [<i>Note:</i> The form <code>[&,this]</code> is redundant but
    accepted for compatibility with ISO C++ 2014. — <i>end note</i>]</del>
    <ins>A <i>lambda-capture</i> shall contain no more than one <i>capture-default</i>.</ins>
    Ignoring appearances in <i>initializer</i>s of <i>init-capture</i>s, an identifier or
    <code>this</code> shall not appear more than once in a <i>lambda-capture</i>.
    [<i>Example:</i>
<pre>
  struct S2 { void f(int i); };
  void S2::f(int i) {
    [&amp;, i]{ };        // OK
    [&amp;, &amp;i]{ };       // <ins>OK</ins>
    <ins>[&amp;, i, &amp;]{ };     // error: more than one capture-default</ins>
    [=, *this]{ };    // OK
    [=, this]{ };     // <ins>OK</ins>
    [i, i]{ };        // error: i repeated
    <ins>[i, &amp;i]{ };       // error: i repeated</ins>
    [this, *this]{ }; // error: this appears twice
}
</pre>
    — <i>end example</i>]
</p>
</blockquote>

<h2><a name="References">5. References</a></h2>

<dl>

<dt><a name="Bolas">[Bolas]</a></dt>
<dd>
std-proposals forum thread "P0756R0: Lambda syntax should be more liberal in what it accepts" (July–August 2017).<br>
<a href="https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/gQnC5Bkd224/FX7D7OkrBgAJ">
https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/gQnC5Bkd224/FX7D7OkrBgAJ</a>.
</dd>

<dt><a name="N4659">[N4659]</a></dt>
<dd>
"Working Draft, Standard for Programming Language C++" (March 2017).<br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf</a>.
</dd>

<dt><a name="P0409R2">[P0409R2]</a></dt>
<dd>
Thomas Köppe. "Allow lambda capture <code>[=, this]</code>" (March 2017).<br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0409r2.html">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0409r2.html</a>.
</dd>

</dl>

</body>
</html>
