Let by-name implicit parameters have lazy semantics
See original GitHub issueMotivation
Generic programming often exhibits scenarios where an implicit expansion would diverge, were it not for a lazy implicit value that “ties the knot”. Current Shapeless has the Lazy
pseudo-type to handle this using some tricky macro machinery. Following an idea of @milessabin it seems cleaner to put this in the language and tie it to by-name implicit parameters.
Status Quo
By-name implicit parameters are disallowed in Scala-2. They have been introduced recently in dotty, but without attaching special meaning to them.
Proposal
Modify implicit search as follows:
When searching for an implicit value of type T
to provide an argument for a by-name parameter of type => T
:
-
Create a new implicit value with a fresh name lv, which has the signature of the following definition:
implicit lazy val lv: T
The current implementation uses the prefix
$lazy_implicit$
followed by a unique integer for lv. -
This lazy val is not immediately available as candidate for implicit search (making it immediately available would result in a looping implicit computation). But it becomes available in all nested contexts that look again for an implicit argument to a by-name parameter.
-
If this implicit search succeeds with expression
E
, andE
contains references to the lazy implicit value lv, replaceE
by{ implicit lazy val lv: T = E; lv }
Otherwise, return
E
unchanged.
Implementation Status
This proposal has been implemented in #1993. The test cases in that PR starting with
lazy-implicits-... . scala
show where the feature is useful. All these test cases would have given a diverging implicit expansion before the change.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:46
- Comments:21 (18 by maintainers)
Top GitHub Comments
For personal reasons, I vote against using @rec 😄 or at least, to wrap it in backticks
@rec
so it doesn’t send me emailWhen declaring the lazy implicit, would it not make more sense to use the
lazy
keyword rather than=>
? It will introduce inconsistency and I can already see myself having to continually explain over the years that=>
parameters are by-name unless implicit in which case they’re by-need.instead of
Going even further maybe there should be a way to declare by-need parameters in general. Then regardless of whether a param is implicit or not, parameters could be by-value, by-name, by-need, and it would be consistent.