implicits よさらば
Scala 3 のコンテキスト抽象
implicit の概要、Scala 2 での問題点
Scala 2 と Scala 3 での実践での相違点
implicits は私達を強化する。
コンテキストの提供、機能の追加、型クラス、暗黙の変換など。
implicits は私達をみじめにする。
おまじない的 import 文。こそこそした変換。
コンテキストの提供、機能の追加、型クラスなどについて
Scala 2 と Scala 3 の比較
- implicit vals
implicit val ec: ExecutionContext = ExecutionContext.global
Future {
def apply[T](body: => T)(implicit executor: ExecutionContext): Future[T] = {...}
}
Scala 2
val myFuture: Future[Int] = Future {
println("Finding the answer...")
42
}
?
?
コンテキストの提供
Scala 2 は implicit val を使う
- using/given
val myFuture: Future[Int] = Future {
println("Finding the answer...")
42
}
Scala 3
given ec: ExecutionContext = ExecutionContext.global
Future {
def apply[T](body: => T)(using executor: ExecutionContext): Future[T] = {...}
}
?
?
コンテキストの提供
Scala 3 は using と given を使う
object other_package {
case class Book(title: String, pages: Int)
}
val book = Book("Winnie-the-Pooh", 160)
myBook.qualifiesForChallenge //true
val book = Book("Too short", 5)
myBook.qualifiesForChallenge //false
implicit class Qualifier(b: Book) {
def qualifiesForChallenge: Boolean = b.pages > 20
}
?
- implicit classes
Scala 2
機能の追加
Scala 2 は implicit クラスを使う
- extension methods
object other_package {
case class Book(title: String, pages: Int)
}
val book = Book("Winnie-the-Pooh", 160)
myBook.qualifiesForChallenge //true
val book = Book("Too short", 5)
myBook.qualifiesForChallenge //false
?
extension (b: Book)
def qualifiesForChallenge = b.pages > 20
Scala 3
機能の追加
Scala は拡張メソッドを使う
trait Scorable[T] {
def score(t: T): Int
}
val book = Book("Dune", 600)
val initialScore = CurrentScore(0).addItem(book) // CurrentScore(600)
val article = Article("Understanding type classes")
val newScore = initialScore.addItem(article) // CurrentScore(601)
- implicit val/object/def (with implicit parameters)
implicit val scorableBook = new Scorable[Book] {
override def score(b: Book): Int = b.pages
}
implicit val scorableArticle = new Scorable[Article] {
override def score(t: Article): Int = 1
}
case class CurrentScore(value: Int) {
def addItem[T](item: T)(implicit scoring: Scorable[T]): CurrentScore =
CurrentScore(value + scoring.score(item))
}
Scala 2
型クラス: 暗黙のパラメータの場合
Scala 2 は implicit val/object/def など
?
- given instances (with using)
given Scorable[Book] with {
override def score(b: Book): Int = b.pages
}
given Scorable[Article] with {
override def score(t: Article): Int = 1
}
case class CurrentScore(value: Int) {
def addItem[T](item: T)(using scoring: Scorable[T]): CurrentScore =
CurrentScore(value + scoring.score(item))
}
trait Scorable[T] {
def score(t: T): Int
}
val book = Book("Dune", 600)
val initialScore = CurrentScore(0).addItem(book) // CurrentScore(600)
val article = Article("Understanding type classes")
val newScore = initialScore.addItem(article) // CurrentScore(601)
Scala 3
型クラス: using の場合
Scala 3 は given インスタンス
?
- implicit def
case class Item(value: String) extends AnyVal
def print(item: Item): Unit = println(s"*** ${item.value} ***")
val book = Book("Dune", 600)
print(book)
?
implicit def bookToItem(book: Book): Item = Item(book.title)
Scala 2
暗黙の変換
Scala 2 は implicit def
- Conversion class
case class Item(value: String) extends AnyVal
def print(item: Item): Unit = println(s"*** ${item.value} ***")
val book = Book("Dune", 600)
print(book)
?
given Conversion[Book, Item] with
def apply(book: Book): Item = Item(book.title)
Scala 3
暗黙の変換
Scala 3 は Conversion 型クラス
機序ではなく意図を表した構文
given Finished[Presentation] with {
override def ask(q: Question): Unit = q.ask()
}
ご清聴ありがとうございました