Scala3 Implicit
Posted 楠爸自习室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala3 Implicit相关的知识,希望对你有一定的参考价值。
Scala3 did lots of improvement in Implicit, which is the most painful feature in Scala2.
A quick summary is
-
Improve the error log to help the developer find the correct implicit instance. -
Split the implicit feature into given/using and extension to make the feature more clear.
Now let's have a taste of these features.
How to pass parameters implicitly?
Scala2
def add(x: Int)(implicit y: Int): Int = x + y
implicit val instance: Int = 10 // :Int = 10
add(1) // :Int = 11
add(1)(5) // :Int = 6
Scala3
def add(x: Int)(using y: Int): Int = x + y
given instance: Int = 10
add(1) // :Int = 11
add(1)(using 5) // :Int = 6
Difference
-
Replace implicit
withusing
in function parameter -
Replace implicit val
withgiven
in instance definition -
Use using
explicitly when giving explicit value
With these changes, the code readability is improved. At least we can search given
to find the implicit instances and search using
to find the implicit parameters.
How to use context bound?
Scala2
trait Show[A] {
def show(x: A): String
}
def printListWithUsing[A](list: List[A] "A")(implicit show: Show[A]): String = list.map(x => show.show(x)).mkString(";")
def printListWithContextBound[A:Show](list: List[A] "A:Show"): String = list.map(x => implicitly[Show[A]].show(x)).mkString(";")
implicit val intShow: Show[Int] = new Show[Int] {
def show(x: Int): String = x.toString
}
printListWithUsing(List(1, 2, 3, 4)) // :String = "1;2;3;4"
printListWithContextBound(List(1, 2, 3, 4)) // :String = "1;2;3;4"
Scala3
trait Show[A] {
def show(x: A): String
}
def printListWithUsing[A](list: List[A] "A")(using show: Show[A]): String = list.map(x => show.show(x)).mkString(";")
def printListWithContextBound[A:Show](list: List[A] "A:Show"): String = list.map(x => summon[Show[A]].show(x)).mkString(";")
given intShow: Show[Int] with {
def show(x: Int): String = x.toString
}
printListWithUsing(List(1, 2, 3, 4)) // :String = "1;2;3;4"
printListWithContextBound(List(1, 2, 3, 4)) // :String = "1;2;3;4"
Difference
-
Replace
implicitly
withsummon
-
Replace
new class
withwith
Not like Scala2, we don't need to new the implicit class explicitly, all the members of class will be wrapped by
with
keyword.implicit val intShow: Show[Int] = new Show[Int] { ... } // Scala2
given intShow: Show[Int] with { ... } // Scala3
How to add function to an existing class?
Scala2
trait Show[A] {
def show(x: A): String
}
implicit class ShowOps[A: Show](v: A "A: Show") {
def show(): String = implicitly[Show[A]].show(v)
}
implicit val intShow: Show[Int] = new Show[Int] {
def show(x: Int): String = x.toString
}
implicit def listShow[A: Show]: Show[List[A]] = new Show[List[A]] {
def show(v: List[A]): String = v.map(_.show()).mkString(";")
}
1.show() // :String = "1"
List(1, 2, 3).show() // :String = "1;2;3"
Scala3
trait Show[A] {
extension (v: A) {
def show(): String
}
}
given intShow: Show[Int] with {
extension (v: Int) {
def show(): String = v.toString()
}
}
given listShow[A: Show]: Show[List[A]] with {
extension (v: List[A]) {
def show(): String = v.map(_.show()).mkString(";")
}
}
1.show() // :String = 1
List(1, 2, 3).show() // :String = "1;2;3"
Difference
In Scala2, we usually define a type class first, then use an implicit class to add the function to the existing type.
In Scala3, it becomes straightforward, use a new keyword extension
to do that.
The magic thing is all the methods in extension
will be translated to functions, the following two expressions are equal
extension(v: Int) {
def demo():String = v.toString
}
// equals to def demo(v: Int)() = v.toString
1.demo() // :String = 1
demo(1)() // :String = 1
Summary
According to my experience, Scala3 implicit is easier than Scala2, but there are still complicated rules for implicit finding, will talk about them later.
You can find the demo code here
-
Scala2 [1] -
Scala3 [2]
参考资料
Scala2: https://gist.github.com/sjmyuan/b17cccaecea669d88e65b9c89f3efeb5
[2]Scala3: https://gist.github.com/sjmyuan/e588de4ec27b735d8cda97050237fd8d
关注【楠爸自习室】
以上是关于Scala3 Implicit的主要内容,如果未能解决你的问题,请参考以下文章
错误代码:1267。操作“=”的排序规则(utf8_general_ci,IMPLICIT)和(utf8_unicode_ci,IMPLICIT)的非法混合