?=> 在 Scala 中是什么意思?

Ian*_*Ian 8 types symbols scala function scala-3

我已经看到这个?=>符号出现在 Scala 代码和一些关于 Scala 3 的讨论帖子中,所以我假设它是一个 Scala 3+ 符号。通过文档或 Google 搜索时什么也没有出现,但它看起来像是Function类型的语法糖,所以它可能与类型和函数有关。这是什么意思?

use*_*ser 5

The type (a: A, b: B, ..., z: Z) ?=> R basically means (using a: A, b: B, ..., z: Z) => R (I believe the latter syntax was valid at one point, but not anymore). All of those parameters become implicit parameters when you use ?=>. Similarly, a function literal (a, b, ..., z) ?=> ... makes all of the parameters to that function implicit, and they can be passed implicitly to other methods later.

Here's an example (Scastie):

case class Foo(s: String)
case class Bar(i: Int)

def baz(xyzzy: (Foo, Bar) ?=> String): Unit =
  val foo = Foo("waldo")
  val bar = Bar(2)
  println(xyzzy(using foo, bar))
Run Code Online (Sandbox Code Playgroud)

baz takes a context function. Note how xyzzy is called with the same syntax as a normal method taking a Foo and a Bar as implicit parameters (in Scala 3, blah(using bleh, bluh) is used to explicitly pass implicit arguments bleh and bluh instead of simply blah(bleh, bluh) like in Scala 2).

Here's one way we can call baz, by defining a method with implicit parameters:

def foobar(using Foo, Bar) =
  val foo = summon[Foo]
  val bar = summon[Bar]
  s"Method - foo: $foo, bar: $bar"

baz(foobar)
Run Code Online (Sandbox Code Playgroud)

We can also pass in a function literal. There are no regular parameters, so it looks a little like a by-name parameter. There are implicit instances of Foo and Bar available because of the (Foo, Bar) ?=> type of the literal.

baz {
  val foo = summon[Foo]
  val bar = summon[Bar]
  s"Function literal - foo: $foo, bar: $bar"
}
Run Code Online (Sandbox Code Playgroud)

You can also use ?=> in the function literal itself to name the implicit parameters without having to summon them and assign them to values. Since they're implicit, you can also call foobar from above because an implicit Foo and Bar are available (you can also do this in the second example despite not having named the parameters explicitly).

baz { (foo: Foo, bar: Bar) ?=>
  val fromMethod = foobar
  s"Explicit context function literal - foo: $foo, bar: $bar; $fromMethod"
}

Run Code Online (Sandbox Code Playgroud)

  • 我认为在 Scala 2 中没有一种简单的方法可以在不使用带有两个隐式参数的方法创建特征 `ContextFunction2[A, B]` 的情况下做到这一点。 (3认同)