question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Let by-name implicit parameters have lazy semantics

See original GitHub issue

Motivation

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, and E contains references to the lazy implicit value lv, replace E 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:closed
  • Created 7 years ago
  • Reactions:46
  • Comments:21 (18 by maintainers)

github_iconTop GitHub Comments

31reactions
reccommented, Feb 20, 2017

For personal reasons, I vote against using @rec 😄 or at least, to wrap it in backticks @rec so it doesn’t send me email

10reactions
japgollycommented, Feb 18, 2017

When 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.

implicit def SumCountable[T, U](implicit ev1: lazy Countable[T]) = ...
// or
implicit def SumCountable[T, U](implicit lazy ev1: Countable[T]) = ...

instead of

implicit def SumCountable[T, U](implicit ev1: => Countable[T]) = ...

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.

def egByValue[A](a: A)(implicit x: X[A]) = ...

def egByName[A](a: => A)(implicit x: => X[A]) = ...

def egByNeed[A](lazy a: A)(implicit lazy x: X[A]) = ...
def egByNeed[A](a: lazy A)(implicit x: lazy X[A]) = ...
Read more comments on GitHub >

github_iconTop Results From Across the Web

Implicit parameters - ACM Digital Library
This paper introduces a language feature, called implicit pa- rameters, that provides dynamically scoped variables within a statically-typed. Hindley-Milner.
Read more >
Implicit Function Types - Scala 3 - EPFL
Implicit parameters solve one half of the problem. Implicit parameters do not have to be propagated using boilerplate code; the compiler takes ...
Read more >
Implicits | Scala 2.13
A method or constructor can have only one implicit parameter list, ... construction of recursive values we allow implicit arguments to be marked...
Read more >
Understand and implement laziness with examples in Scala ...
Lazy parameters are not evaluated until they're used, and in languages that allow explicitly marked lazy parameters, lazy parameters are by-name.
Read more >
Difference between Scala 2 implicits and Scala 3 given/using
You can also have implicit by-name parameters in Scala 3. Given. Givens are also pretty similar to implicit vals/objects/methods. One nice thing ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found