Description
It seems we have implicit consensus on given
as the new name for implicit instances. It has a lot more support than its alternative delegate
. So, let's take that as a given 😉
given
is a good name for instances, but it does have a potential problem that given
parameters and given
instances are too easily confused. The example that made this painfully clear for me was in #7056, where we find:
given [T1 <: NonEmptyTuple, TZ <: Tuple] as Aux[T1, Head[T1] *: TZ]
given Aux[Tail[T1], TZ] = new Idnt[T1] {
type Res = Head[T1] *: TZ
def (t1: T1) idnt: Res = t1.head *: t1.tail.idnt
}
At first, I could make neither heads nor tails of it and thought that the parser was faulty. Then I realized that the second given
is a parameter to the first! Sure, it should have been indented but still... The syntax is dangerously misleading.
One way to fix this is to choose different names for introducing parameters and instances. I.e., go back to delegate
. Another way to fix it is to put given
under parentheses, thereby using the standard way of expressing parameter dependencies. I.e. it would be
def f(x: T)(given Context): T
f(x)(given ctx)
instead of
def f(x: T) given Context: T
f(x) given ctx
This idea, originally proposed by @smarter, is elaborated in #7150 (docs only, no implementation).
One advantage is that it generalizes readily to implicit function types and literals. These would be
(given A) => B
(given x: A) => b
Another advantage is that it makes it possible to have normal parameters after given parameters, something we stopped allowing because the original syntax was so confusing.
A possible downside is in the application of multiple given arguments in one argument list. That would look like
f(given a, b)
instead of
f given (a, b)
The first syntax takes some getting used to, I think.
Another possible option is to keep given
for instance definitions, but use something else for implicit parameters. where
was suggested by @milessabin. But any solution has to work in all of the following cases:
- implicit parameters in methods
- implicit arguments
- implicit function literals
- implicit function types
where
works OK for the first two, but not for the last two.