<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">We've gone around and around a
few times on "unnamed variables" (underscore), starting with JEP
302 (Lambda Leftovers). We reclaimed the underscore token in
Java 9 with the intention of using it for unnamed variables and
"any" patterns. Along the way, we ran into some hiccups, and it
has sat on the shelf for a while. Let's take it down, dust it
off, and see if we have any more clarity than before. <br>
<br>
There are three syntactic productions in which we might want to
use underscore as a "don't care" indicator:<br>
<br>
- Unnamed variables. Here, underscore stands in for a variable
name. When we declare a local variable, catch formal, pattern
variable, etc, whose name is `_`, which has the effect of
entering no new names in scope. It becomes an "initialize-only"
variable. <br>
<br>
try { ... }<br>
catch (FooException _) { throw new BarException("foo"); }<br>
<br>
- Partial inference. Here, underscore stands in for a type
name. Today, we can infer type variables for generic method
invocations and constructor invocations, but it is
all-or-nothing. Being able to denote "infer this type" would
allow us to do partial inference:<br>
<br>
foo.<String, _>m(...)<br>
<br>
- "Any" patterns. Here, underscore is a pattern, which matches
everything, and binds nothing.<br>
<br>
case Foo(var s, _): ...<br>
<br>
We don't have to do all of these; right now we're not
considering partial inference, but the other two are reasonable
options. Unnamed variables have been a long-standing request;
any patterns will likely be a common request soon as well.<br>
<br>
For a match-all pattern, there is little to say other than "_"
is one of the alternatives of the Pattern production, it is
applicable to all types, it is unconditional on all types, and
it has no bindings. The specification already has a concept of
"any" patterns; this is just making it denotable. <br>
<br>
<br>
I think there is little controversy about using unnamed local
variables (local variable declaration statements, catch formals,
foreach induction variables, resources in try-with-resources)
and unnamed lambda parameters. What is common to all of these
is that these are _pure implementation details_, where the
author has elected to not give a name to a variable that is
entirely implementation-facing. This seems eminently
reasonable. Unnamed parameters can help eliminate errors by
capturing design assumptions and make life easier for static
analysis tools that like to point out unused variables. <br>
<br>
Where we stumble is on method parameters, because method
parameter names serve two masters -- the implementation (as the
declaration of a variable) and the API (as part of the
specification of what the method does.) Among other things, we
like to document the semantics of method parameters in Javadoc
with the `@param` tag, but doing so requires a name (or
inventing a new Javadoc mechanism like `@param #4`, likely a
loser.) Secondarily, sometimes parameter names are retained in
the MethodParameters attribute, though that attribute (JVMS
4.7.24) already supports parameters without names by using a
zero CP index. <br>
<br>
With `var`, we drew a clear line of "implementation only" -- you
can't infer a method return type, even for a private method, you
can only use it for local variables and lambda formals. This
has been pretty successful. <br>
<br>
We've explored a number of intermediate points on the spectrum
with varying degrees of stability:<br>
<br>
A) Implementation only -- local variables, catch formals,
for-loop induction variables, TWR resources, pattern variables,
lambda formals <br>
B) "A++", where we add in method parameters of anonymous
classes<br>
C) Adding in method parameters _for non-initial declarations_
-- allow unnamed parameters only for methods that override a
method from a supertype, ensuring that there is a real
specification of what the parameters mean.<br>
D) Anything goes, any method parameter can be unnamed, throwing
specification to the wind.<br>
<br>
A is a stable point, and has the advantage of mostly lining up
with where we can use `var`. But users will surely grumble that
they can't use it for implementations of methods from
supertypes. As this feature request predates lambdas and
patterns, giving it to lambdas and patterns but not ordinary
methods might feel a bit mean. <br>
<br>
The motivation for B is obvious -- to support smooth refactoring
between lambdas and inner classes -- but is not a very stable
point, as one will immediately ask "what about refactoring to
named classes". <br>
<br>
C feels attractive, though there would surely be complaints too;
it excludes constructors and static methods (which might
sometimes want unnamed parameters when a parameter is no longer
used, but stays around for binary compatibility), and even some
initial declarations. But, these cases are likely to be
somewhat more rare, so I don't object to leaving these aside.
The main concern is that this might feel arbitrary. There is
also the possibility for some confusion; it is not obvious what
it means when you override a method that already has an unnamed
parameter. Can you give it a name and use it? It is a little
weird that the lack of name applies only to the implementation
of the method, but somehow bleeds into the specification. There
is also some impact on Javadoc, as well as lingering concerns
that there are other shoes to drop other than Javadoc and
MethodParameters. <br>
<br>
D is also stable, but feels like it makes the language less
safe, by making some methods unspecifiable. On the other hand,
the people who might use it for initial declarations, static
methods, etc, are also the sort of people who probably don't
write specification anyway (otherwise they would realize that
they are depriving their callers of useful information.) <br>
<br>
In (C), Javadoc could insert an `@implNote` that says something
like "this implementation ignores the value of parameters
<x> and <y> from declaring method Foo::bar". In
(D), it could say "ignores its 3rd and 4th parameter", or insert
synthetic @param tags for parameters whose name is something
like "<unnamed>". <br>
<br>
Past discussions seemed to gravitate toward either A or D, which
are also the simplest / most stable points. I guess it becomes
a question of getting over the "makes the language less safe"
concerns. <br>
<br>
Regardless, I'd like to see if we can quantify the "lingering
concerns about other shoes to drop." <br>
<br>
</font></font>
</body>
</html>