<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">Thanks for this more detailed
      explanation.  <br>
      <br>
      Here's one thing I would like to drill into, which I hinted at in
      my mail the other day: why we find "imperative" comforting.  I
      proposed two theories:<br>
      <br>
       - Looks like a constructor body in the mirror <br>
       - Nominal association between binding and value is sometimes more
      clear than positional association<br>
      <br>
      Indeed, your comment that "which I would choose likely depends on
      arity" suggests that you are mostly aiming at the latter. 
      Assuming this is most of the answer, it leads me to ask the
      following questions:<br>
      <br>
      1.  In a world where we had a more general mechanism for by-name
      {invocation,matching}, wouldn't we prefer that?  Let's say that
      by-name invocation looked like:<br>
      <br>
          new Point(x: 1, y: 2)<br>
      <br>
      The logical companion at the use site would be:<br>
      <br>
          case Point(x: var a, y: var b):<br>
      <br>
      and the logical companion at the match site would be:<br>
      <br>
          matches Point(x: this.x, y: this.y)<br>
      <br>
      While I'm not ready to commit to this feature, it seems to me the
      possibility that we could have a broader way to associate names
      with values at various parentheses-bounded constructs suggest that
      inventing a fresh one, with more limited applicability, might not
      be ideal.  <br>
      <br>
      2.  Users can already simulate imperative with functional without
      a language feature, and indeed, can do so more flexibly because
      it's not all-or-nothing.  Suppose we had the following imperative
      dtor:<br>
      <br>
          pattern Foo(int a, int b, int c, ... int z) { <br>
              a = this.a;<br>
              b = /* really complicated computation */<br>
              c = this.c;<br>
              ... more trivial bindings ...<br>
              match;<br>
          }<br>
      <br>
      Here, one binding is complex and the rest are trivial.  With
      functional, users can already do:<br>
      <br>
    </font><font size="4" face="monospace">    pattern Foo(int a, int b,
      int c, ... int z) { <br>
              var b = /* really complicated computation */<br>
              match Foo(this.a, b, this.c, ...)<br>
          }<br>
    </font><br>
    <font size="4" face="monospace">Which is to say, if we need to use
      imperative logic to "outline" a complex calculation, the language
      provides features for doing so.  Now, a dtor with so many bindings
      (and worse, all of the same type) is at risk for getting "out of
      sync", but at this point I refer back to argument #1, which is
      that someday we may be able to provide nominal context for these
      expressions to prevent such errors, at which point we can write:<br>
      <br>
              match Foo(a: this.a, b: b, c: this.c, ...)<br>
      <br>
      without having to have two linguistic ways to write a matcher
      (with the attendant "style wars".)  <br>
      <br>
      <br>
      <br>
      <br>
    </font><br>
    <div class="moz-cite-prefix">On 4/4/2024 4:18 PM, Guy Steele wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:AFF4B47B-880C-42ED-8E3D-8B5D960B38B8@oracle.com">
      
      <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
        <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
          <br>
        </div>
        <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
          <div>
            <blockquote type="cite">
              <div>On Apr 4, 2024, at 1:11 PM, Brian Goetz
                <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com"><brian.goetz@oracle.com></a> wrote:</div>
              <br class="Apple-interchange-newline">
              <div><font size="4" face="monospace">There's obviously
                  some more discussion coming about "what is a pattern",
                  but let me summarize the points on which we've asked
                  for syntax feedback, and make another call (I can't
                  believe I have to ask) for opinions here.  <br>
                </font><font size="4" face="monospace">...  <br>
                  <br>
                  Body types.  There is the broad choice of "imperative
                  vs functional"; within that, there are choices about
                  "implicit failure" or "implicit success."  There is
                  also how we indicate success and failure.  The
                  suggested approach is functional, implicit failure,
                  return means fail, success is indicated by `match
                  patternName(BINDINGS)`.<br>
                </font></div>
            </blockquote>
          </div>
          <br>
          <div>
            <div>The draft proposal that Brian sent out on March 29, in
              the section and subsections with these headings:</div>
            <div><br>
            </div>
            <div><span style="font-family: monospace; font-size: large;">##
                Body types</span><br style="font-family: monospace;">
            </div>
            <div><span style="font-family: monospace; font-size: large;">###
                Success and failure</span><br style="font-family: monospace;">
            </div>
            <div><span style="font-family: monospace; font-size: large;">###
                Implicit failure in the functional approach</span><br style="font-family: monospace;">
            </div>
            <div><span style="font-family: monospace; font-size: large;">###
                Implicit success in the imperative approach</span><br style="font-family: monospace;">
            </div>
            <div><span style="font-family: monospace; font-size: large;">###
                Imperative is a trap</span><br style="font-family: monospace;">
            </div>
            <div><span style="font-family: monospace; font-size: large;">###
                Derive imperative from functional?</span><br style="font-family: monospace;">
            </div>
            <div><span style="font-family: monospace; font-size: large;"><br>
              </span></div>
            <div>laid out a version of the functional approach in which
              failure is implicit, a version of the imperative approach
              in which success is implicit, and an add-on to the
              functional approach that allows it to be used in a way
              that is syntactically similar to the imperative approach.
              But this was an incomplete presentation of a design space
              that actually has more possibilities and potential
              symmetries.</div>
            <div><br>
            </div>
            <div>Here I undertake a complete retelling of an imperative
              and approach and a functional approach and then compare
              them. An important difference is that
              <b>I will assume a version of the imperative approach in
                which failure, rather than success, is implicit</b>. The
              reason for this is while we expect simple deconstructors
              always to succeed—and that motivates us to make success
              implicit, to make deconstructors one line shorter—that is
              not true for other kinds of patterns, and I think it is
              good to mark pattern success explicitly no matter which
              approach is used used.</div>
            <div><br>
            </div>
            <div>Here, then, is my retelling. As part of this retelling,
              I will explain pattern-match success in terms of a new
              kind of reason for abrupt completion: “a successful match
              with match results (z1, z2, …, zn)” where each zk is some
              value.</div>
            <div><br>
            </div>
            <div><br>
            </div>
            <div><b>An Imperative Approach (in which failure is
                implicit)</b></div>
            <div><br>
            </div>
            <div>The parameters of a pattern declaration are definitely
              unassigned at the start of the body of the declaration.
              They may be given values through ordinary assignment. For
              expository purposes, let the names of the parameters be
              v1, v2, …, vn.</div>
            <div><br>
            </div>
            <div>If execution of the body completes normally, or
              completes abruptly for any reason other than a successful
              match, then the invocation of the pattern results in a
              failed match. In particular, the statement `return;` may
              be used in the body of a pattern declaration to indicate
              failure to match.</div>
            <div><br>
            </div>
            <div>The statement `match;` (or, if you prefer, `match
              patternName;`, but I will stick with the shorter form for
              now) indicates a successful match. It may be used only
              within the body of a pattern declaration. Execution of
              `match;` causes the body of the pattern declaration to
              complete abruptly, the reason being a successful match
              with match results (v1, v2, …, vn)—that is, the current
              values of the parameters v1, v2, …, vn are used as the
              match results.</div>
            <div><br>
            </div>
            <div>It is a compile-time error if any of the parameters of
              a pattern declaration is not definitely assigned at any
              `match;` statement.</div>
            <div><br>
            </div>
            <div><i>Optional restriction:</i> It is a compile-time error
              if the body of a deconstructor pattern declaration can
              complete normally or contains a `return;` statement. (This
              restriction would imply that a deconstructor cannot fail
              to match. This restriction would not apply to static or
              instance patterns.)</div>
            <div><br>
            </div>
          </div>
          <div>
            <div>
              <div>Here is the Point deconstructor written in the
                imperative style.</div>
              <div>
                <div class="moz-forward-container">
                  <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                    <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">class Point {
    int x, y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // Imperative style
    pattern Point(int x, int y) {
        x = that.x;
        y = that.y;
        match;        // Match success must be signaled explicitly
    }
}</span></font></code></pre>
                  </div>
                </div>
              </div>
              <div>In this imperative style, the deconstructed body
                looks like the “reverse" of the constructor body, with
                the sides of each assignment swapped and `that`
                substituted for `this`—and, of course, the addition of a
                `match` statement to signal success.</div>
              <div><br>
              </div>
              <div><b>Special convenience feature: </b>Another form of
                the `match` statement is provided for convenience:</div>
              <div>
                <div class="moz-forward-container">
                  <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                    <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">    match (e1, e2, …, en);</span></font>
</code><div>
</div><div>means</div></pre>
                  </div>
                </div>
              </div>
              <div>
                <div class="moz-forward-container">
                  <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                    <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">    { var t1 = e1, t2 = e2, …, tn = en; v1 = t1; v2 = t2; … vn = t1; match; }</span></font></code></pre>
                  </div>
                </div>
              </div>
              <div>where temporaries t1, t2, …, tn are fresh local
                variables that do not occur elsewhere in the program.
                (It is a compile-time error if the number of expressions
                does not match the number of parameters, or if for any k
                the type of ek is not assignment-compatible with the
                declared type of vk.)</div>
              <div><br>
              </div>
              <div>This allows the deconstructor for Point to be written
                this way instead if desired:</div>
              <div>
                <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                  <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                    <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                      <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                        <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                          <div class="moz-forward-container">
                            <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                              <pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 1em; line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">    // Imperative style, but using the extended `match` statement to abbreviate a series of boilerplate assignments
    pattern Point(int x, int y) {
        match (that.x, that.y);
    }</code></pre>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div>
                <div><br>
                </div>
                <div><br>
                </div>
              </div>
              <div>
                <div><b>Alternatively, a Functional Approach </b><b>(in
                    which failure is likewise implicit)</b></div>
                <div><br>
                </div>
                <div>
                  <div>[This is very close to what Brian proposed, but I
                    express it in the same detailed terms that I used
                    above to describe the variant imperative approach
                    that assumes failure is implicit.]</div>
                  <div><br>
                  </div>
                  <div>If execution of the body completes normally, or
                    completes abruptly for any reason other than a
                    successful match, then the invocation of the pattern
                    results in a failed match. In particular, the
                    statement `return;` may be used in the body of a
                    pattern declaration to indicate failure to match.</div>
                  <div><br>
                  </div>
                  <div>For expository purposes, let the names of the
                    parameters of the pattern be v1, v2, …, vn.</div>
                  <div><br>
                  </div>
                  <div>The statement `match (e1, e2, …, en);` (or, if
                    you prefer, `match patternName(e1, e2, …, en);`, but
                    I will stick with the shorter form for now)
                    indicates a successful match, using the values of
                    the expressions e1, e2, …, en. It may be used only
                    within the body of a pattern declaration. Execution
                    of `match (e1, e2, …, en);` causes the body of the
                    pattern declaration to complete abruptly, the reason
                    being a successful match with match results (z1, z2,
                    …, zn), where z1, z2, …, zn are the respective
                    results of evaluating the expressions e1, e2, …, en
                    (working left-to-right). If evaluation of any en
                    completes abruptly, then evaluation of `match (e1,
                    e2, …, en);` completes abruptly for the same reason.</div>
                  <div><br>
                  </div>
                  <div>It is a compile-time error if the number of
                    expressions does not match the number of parameters,
                    or if for any k the type of ek is not
                    assignment-compatible with the declared type of vk.</div>
                  <div><br>
                  </div>
                  <div><i>Optional restriction:</i> It is a compile-time
                    error if the body of a deconstructor pattern
                    declaration can complete normally or contains a
                    `return;` statement. (This restriction would imply
                    that a deconstructor cannot fail to match. This
                    restriction would not apply to static or instance
                    patterns.)</div>
                  <div><br>
                  </div>
                  <div>Here is the Point deconstructor written in the
                    functional style.</div>
                  <div>
                    <div class="moz-forward-container">
                      <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                        <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">class Point {
    int x, y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // Functional style
    pattern Point(int x, int y) {
        match (that.x that.y);
    }
}</span></font></code></pre>
                      </div>
                    </div>
                  </div>
                  <div><br>
                  </div>
                  <div>In the functional style, the `match` statement
                    that signals success looks somewhat like an
                    invocation that provides desired values
                    corresponding to the declared parameters.</div>
                  <div><br>
                  </div>
                  <div>The parameters of a pattern declaration are in
                    fact declared local variables that are definitely
                    unassigned at the start of the body of the
                    declaration. They may be given values through
                    ordinary assignment, but need not be; the compiler
                    will not complain just because a pattern parameter
                    goes unused as a local variable. One possible use
                    for them is to hold values intended to be match
                    results while other values are still being computed.</div>
                  <div><br>
                  </div>
                  <div>
                    <div>
                      <div><b>Special convenience feature: </b>Another
                        form of the `match` statement is provided for
                        convenience:</div>
                      <div>
                        <div class="moz-forward-container">
                          <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                          </div>
                        </div>
                      </div>
                    </div>
                    <div>
                      <div class="moz-forward-container">
                        <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                          <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">    match;</span></font>
</code><div>
</div><div><font face="Helvetica"><span style="white-space: normal;">means</span></font></div></pre>
                        </div>
                      </div>
                    </div>
                    <div>
                      <div class="moz-forward-container">
                        <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                          <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">    match (v1, v2, …, vn);</span></font></code></pre>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div>
                    <div>where v1, v2, …, vn are the names of the
                      declared pattern parameters.</div>
                    <div><br>
                    </div>
                    <div>This allows the deconstructor for Point to be
                      written this way instead:</div>
                    <div>
                      <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                        <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                          <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                            <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                              <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                                <div class="moz-forward-container">
                                  <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                                    <pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 1em; line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">    // Functional style, but using parameter variables for convenience to stash intermediate match result values as they are computed
    pattern Point(int x, int y) {
<span style="font-size: 15.3px;">        x = that.x;
        y = that.y;
        match;</span>
    }</code></pre>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div>
                <div>It is a compile-time error if any of the parameters
                  of a pattern declaration is not definitely assigned at
                  any `match;` statement.</div>
                <div><br>
                </div>
                <div><br>
                </div>
                <div><b>Comparing These Imperative and Functional
                    Approaches</b></div>
                <div><br>
                </div>
                <div>The two approaches are described from different
                  perspectives, and suggest slightly different
                  implementation techniques, but <b>they allow the
                    programmer to write exactly the same set of programs</b>.
                  Assuming reasonable compiler optimization of chained
                  assignments and unused local variables, <b>the
                    resulting machine code should be the same in either
                    case</b>. Whether or not to use explicit assignment
                  to the pattern parameter variables becomes entirely a
                  matter of taste. If the number of parameters is, say,
                  4 or less, I would probably prefer to write a pattern
                  in the functional style, to cut down on clutter. But
                  if the number of parameters is, say, 7 or more, I
                  would probably prefer to write a pattern in the
                  imperative style, to make it easier to see that each
                  match result has been assigned to the correct
                  parameter. In between, my mileage might vary.</div>
              </div>
            </div>
            <div><br>
            </div>
            <div><b>It would seem, then, from these explanations and
                examples, that we could choose either of these models as
                the “official” explanation of how the bodies of pattern
                declarations work.</b> I actually thought that for a
              little while. It does seem that either is easily derived
              from the other by introducing a plausible “special
              convenience feature”.</div>
            <div><br>
            </div>
            <div><b>But</b> if we want to be able to use the SAP
              (single-abstract-pattern interfaces) feature that Brian
              introduces toward the end, in his section</div>
            <div><br>
            </div>
            <div><span style="font-family: monospace; font-size: large;">##
                Pattern lambdas</span><br style="font-family: monospace;">
            </div>
            <div><br>
            </div>
            <div>so that patterns can be expressed as lambda
              expressions, then <b>the functional approach is clearly
                the better choice</b>. To see why, consider his example:</div>
            <div>
              <div>
                <div>
                  <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                    <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                      <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                        <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                          <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                            <div class="moz-forward-container">
                              <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                                <pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 1em; line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">    <span style="white-space: normal; font-family: monospace; font-size: large;">interface Converter<T,U> {</span>
        <span style="white-space: normal; font-family: monospace; font-size: large;">pattern(T t) convert(U u);</span>
    }</code></pre>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div>
                <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                  <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                    <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                      <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                        <div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
                          <div class="moz-forward-container">
                            <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                              <pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 1em; line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace; margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">    <span style="white-space: normal; font-family: monospace; font-size: large;">Converter<Integer, Short> c =</span>
    <span style="white-space: normal; font-family: monospace; font-size: large;">    i -> {</span>
<span style="font-size: 15.3px;">    </span><span style="white-space: normal; font-family: monospace; font-size: large;">        if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE)</span><span style="font-size: 15.3px;">
</span><span style="white-space: normal; font-family: monospace; font-size: large;">                match Converter.convert((short) i);</span><span style="font-size: 15.3px;">
        };</span></code></pre>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <div>
              <div>This lambda expression is, of course, written in the
                functional style. But watch what happens if we try to
                write it in the imperative style:</div>
              <div>
                <div class="moz-forward-container">
                  <div class="markdown-here-wrapper" data-md-url="" markdown-here-wrapper-content-modified="true">
                    <pre style="line-height: 1.2em; margin-top: 1.2em; margin-bottom: 1.2em;"><code style="margin: 0px 0.15em; background-color: rgb(248, 248, 248); overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;"><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">    </span></font><span style="font-size: large; white-space: normal;">Converter<Integer, Short> c =</span><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">
        </span></font><span style="font-size: large; white-space: normal;">i -> {</span><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">
</span></font><span style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 15.3px;">  </span><span style="white-space: normal; font-size: large;">          if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {</span><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">
                u = (short) I;    // PROBLEM: u is not in scope
                match;
            }
        };
</span></font></code><div><font face="Consolas, Inconsolata, Courier, monospace"><span style="font-size: 15.3px;">
</span></font></div></pre>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div>The problem is that the parameter name `u` is declared in
            the SAP interface `Converter` but is not in scope within the
            lambda expression. This, I think, is reason enough to regard
            the functional approach as the “official explanation” of
            what is going on, because, as with methods and the way they
            bind method parameters to argument values, the baseline
            mechanism in Java for establishing correspondence between
            parameters and values is order within a sequence rather than
            matching of parameter names.</div>
          <div><br>
          </div>
          <div>So, in the end, I recommend adopting the functional
            approach, but I also recommend adopting the “special
            convenience feature” so that the syntactic style of the
            imperative approach can be used in certain common cases.</div>
          <div><br>
          </div>
          <div>—Guy</div>
          <div><br>
          </div>
          <div><br>
          </div>
          <div><br>
          </div>
          <div><br>
          </div>
          <div><br>
          </div>
          <div><br>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>