Skip to content

Update implicit-conversions.md #2674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 19, 2023
64 changes: 62 additions & 2 deletions _tour/implicit-conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,69 @@ In the second case, a conversion `c` is searched for, which is applicable to `e`

An example is to compare two strings `"foo" < "bar"`. In this case, `String` has no member `<`, so the implicit conversion `Predef.augmentString("foo") < "bar"` is inserted. (`scala.Predef` is automatically imported into all Scala programs.)

### How are implicit conversions selected?
### How are implicit conversions brought into scope? ###

See this [Scala FAQ Answer](https://docs.scala-lang.org/tutorials/FAQ/index.html#where-does-scala-look-for-implicits).
{% tabs implicit-conversion-scope class=tabs-scala-version %}
{% tab 'Scala 2' %}
In Scala 2, an implicit conversion is brought into scope by importing from the object that defined it, (e.g. `Conversions` in this case). If the implicit conversion is in the companion object of the argument type, (e.g. `Student` in this case), then no import is necessary.

```scala
import scala.language.implicitConversions // required to define an implicit conversion

case class Student(name: String)
object Student {
implicit def fromStudentToInt(student: Student): Int = student.name.length
}

object Conversions {
implicit def fromStringToStudent(name: String): Student = Student(name)
}

import Conversions._
object Usage {
def main(args: Array[String]) = {
val reginald: Student = "Reginald" // applies the conversion Conversions.fromStringToStudent
println(reginald + 2) // applies the conversion Student.fromStudentToInt
}
}
```
{% endtab %}
{% tab 'Scala 3' %}
In Scala 3, an implicit conversion is brought into scope by either importing `given` or the named conversion from the object that defined it, (e.g. `Conversions` in this case).

Note that as of Scala 3, implicit conversions cannot be brought into scope anymore by means of a wildcard import (`*`).

Given the example:

```scala
case class Student(name: String):
def printName: Unit = println(name)
object Student:
given Conversion[Student, Int] = _.name.length

object Conversions:
given fromStringToStudent: Conversion[String, Student] = Student(_)
```

The following imports would bring the `Conversion[String, Student]` into scope:
- `import Conversions.given`
- `import Conversions.{given Conversion[String, Student]}`
- `import Conversions.fromStringToStudent`

If the implicit conversion is in the companion object of the argument type, (e.g. `Student` in this case), then no import is necessary.

```scala
import Conversions.given
object Usage:
@main def run =
val reginald: Student = "Reginald" // applies the Conversion[String, Student]
println(reginald + 2) // applies the Conversion[Student, Int]
```
{% endtab %}
{% endtabs %}

Further reading:
- [Where does Scala look for implicits? (on StackOverflow)](https://docs.scala-lang.org/tutorials/FAQ/index.html#where-does-scala-look-for-implicits).

### Beware the power of implicit conversions

Expand Down