Синтаксис для именованных заданных / используемых объектов в Scala 3 (Dotty)
Есть ли однострочный способ предоставить именованную ссылку на значение, которое должно быть неявно доступным (т. Е. Доступным с
using
синтаксис) без устаревшего
implicit
ключевое слово? Согласно документам , я бы ожидал, что следующее будет работать (под SBT,
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
...
но я бы хотел сделать это в одном выражении, а не в двух. Тот же комментарий применяется к определению данного в первую очередь, а затем к привязке его к имени:
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
}
но мне это кажется шаблонным.
1 ответ
Оказывается,
given x: T = ...
синтаксис был добавлен между ревизией M2 и ревизией RC1. Следующие работы с
scalaVersion := "3.0.0-RC1"
:
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 with {
override def sayHello(username: String): Unit = println(s"Hello, ${username}!")
override def shutdown(): Unit = println("Shutting down")
}
try {
greet("world")
} finally {
greeter.shutdown()
}
}