Currently, view bounds are causing a deprecation error:
class A
def f[T <% A](x: T) = { val a: A = x; ??? }
^
view bounds `<%' are deprecated, use a context bound `:' instead
However, this is what we get and it’s misleading:
def f[T : A](x: T) = ??? // that is:
def f[T](x: T)(using A[T]) = ???
What we want instead is:
import scala.language.implicitConversions
def f[T](x: T)(using Conversion[T, A]) = { val a: A = x; ??? }
Or, alternatively:
def f[T](x: T)(using T => A) = { val a = summon[T => A](x); ??? }
, which brings back the boilerplate the view bound was supposed to remove (maybe the reason it was deprecated?) On the other hand, this syntax is going to be more and more used as we want to avoid implicit conversion. Indeed, the recommended way to express this:
def f(a: A) = ???
given Conversion[String, A] = ???
import scala.language.implicitConversions
f("hello")
, is to apply the conversion explicitly and push it in the library code with a using clause:
def f[T](x: T)(using c: T => A) = { val a = c(x); ??? }
We may call this pattern anticipated implicit conversion or anticipated conversion for short. My proposal is to introduce an extension method as
to simplify the conversion application:
extension [T](x: T)
def as[A](using c: T => A) = c(x)
def f[T](x: T)(using T => A) = { val a = x.as[A]; ??? }
Or, in view bound syntax, which gets back all its relevance:
def f[T <% A](x: T) = { val a = x.as[A]; ??? }