<!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>