2

Is it possible to create an unnamed implicit class or function in Scala?

For example, if I have the following implicit class:

implicit class ListIntExtras(list: List[Int]) {
  def average = list.sum / list.size
}

I would prefer to be able to define it as something like implicit class _(list: List[Int]) because the name of the class ListIntExtras is never actually used anywhere.

And the same goes for an implicit function:

implicit def intToDouble(i: Int): Double = i.toDouble

I would like to instead define that method as implicit def _(i: Int): ... because, again, I am never referencing its actual name.

I know that this is possible for implicit vals. For example, you can do implicit val _ = new Config() which is useful because naming it anything other than _ seems like just a waste as it is never being referenced by name.

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
socom1880
  • 340
  • 3
  • 12

3 Answers3

2

Scala 3 (Dotty) provides dedicated extension methods syntax which effectively avoids having to give a name to implicit class, for example

scala> extension (list: List[Int])
     |       def average = list.sum / list.size
     |
def extension_average(list: List[Int]): Int

scala> List(1, 41).average
val res0: Int = 21
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
1

No, you can't create a class or method without an identifier. It is not valid syntax.

implicit val _ = new Config() doesn't really do what you think it does. The underscore is being used as an identifier for the val, which cannot be reused in the same scope. You can refer to it by name:

val a: Config = `_`

However in cases like this (and most others):

implicit val Some(_) = Option(1)

The underscore means do not assign the value to anything.

There's no reason to have a val or def that you cannot reach by an identifier. If you're worried about name collisions, then you should make the name longer and more unique. However, not having a name would prevent someone from doing a wildcard import and excluding a single implicit from scope:

e.g.

import package.MyImplicits.{ badImplicit => _, _}
Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
  • Note that `implicit val _ = new Config` does work, just not in the REPL which tries to bind the symbol. Anyways, if you do that, the implicit is not found because it doesn't have a symbol. – 0__ Mar 02 '16 at 21:27
  • It looks like `implicit val _` does actually work. I've been using it in my projects with the Play json library for the `Format` property of case classes (`implicit val _ = Json.format[A]`). Removing that gives an error saying it could not find a `Format` for class A. – socom1880 Mar 02 '16 at 21:58
  • @socom1880 I fixed that part, but it doesn't change the overall answer. The val still has an identifier. – Michael Zajac Mar 02 '16 at 22:14
  • @m-z Not sure I follow... Are you saying that using underscore does in fact give an identifier of `_` and I wouldn't be able to create any other val with an identifier of `_` in that same scope? And to follow up to you saying "There's no reason to have a val or def that you cannot reach by an identifier", couldn't it still be useful if it is an implicit val? You often don't refer to those by their identifiers. – socom1880 Mar 02 '16 at 22:38
  • There are some examples of underscore madness at the link I offered. They briefly disallowed underscore as an identifier, but Java allowed it at the time so it was restored; but eventually it will disappear from Java, too. – som-snytt Mar 02 '16 at 22:49
0

This is a big ask at Typelevel Scala:

https://github.com/typelevel/scala/issues/9

The tricky part would be, the underlying implicit has to have a name, so how do you generate a name that is useful? It can't be a fresh name, because you want it to be stable across compilations and not affected by textual order. Maybe the name would encode its signature; though sometimes you want ambiguous implicits in scope, too.

som-snytt
  • 39,429
  • 2
  • 47
  • 129