-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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 ctxThis 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) => bAnother 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.