すぐに非推奨になるキーワードなしで、暗黙的に利用できる (つまり、構文で利用できる) 値への名前付き参照を提供する 1 行の方法はありますか? docsによると、次のように動作することが期待されます (SBT の下で、:using
implicit
scalaVersion := "3.0.0-M2"
trait Greeter {
def sayHello(username: String): Unit
def shutdown(): Unit
}
def greet(username: String)(using g: Greeter): Unit = {
g.sayHello(username)
}
object Foo extends App {
given greeter: Greeter = new Greeter {
override def sayHello(username: String): Unit = println(s"Hello, ${username}!")
override def shutdown(): Unit = println("Shutting down")
}
try {
greet("world")
} finally {
greeter.shutdown()
}
}
しかし、これは失敗します
[error] -- Error: /path/to/project/src/main/scala/Foo.scala:12:15
[error] 12 | given greeter: Greeter = new Greeter {
[error] | ^
[error] | end of statement expected but ':' found
[error] -- [E040] Syntax Error: /path/to/project/src/main/scala/Foo.scala:12:17
[error] 12 | given greeter: Greeter = new Greeter {
[error] | ^^^^^^^
[error] | ';' expected, but identifier found
現在: これをさまざまな方法で回避できますが、ドキュメントが混乱している (または間違っている) か、かなり基本的なことを誤解しています。
回避策 1 (ここで提案されているとおり):
lazy val greeter: Greeter = new Greeter {
override def sayHello(username: String): Unit = println(s"Hello, ${username}!")
override def shutdown(): Unit = println("Shutting down")
}
given Greeter = greeter
...
しかし、これを 2 つではなく 1 つの式で実行できるようにしたいと考えています。同じコメントが、最初に指定されたものを定義してから名前にバインドする場合にも当てはまります。
given Greeter with {
override def sayHello(username: String): Unit = println(s"Hello, ${username}!")
override def shutdown(): Unit = println("Shutting down")
}
val greeter: Greeter = implicitly
implicitly
特に、3.1 で非推奨になり、3.2 でなくなると思うので。
これを回避するために、指定されたオブジェクトの呼び出しを関数でラップすることもできます。
def greet(username: String)(using g: Greeter): Unit = {
g.sayHello(username)
}
def shutdown(using greeter: Greeter): Unit = {
greeter.shutdown()
}
given Greeter with {
override def sayHello(username: String): Unit = println(s"Hello, ${username}!")
override def shutdown(): Unit = println("Shutting down")
}
try {
greet("world")
} finally {
shutdown
}
しかし、それは定型的なようです。