我正在尝试在 Scala 3 中创建上下文函数的匿名实现。具体代码如下:
def mem[E, A](block: Raise[E] ?=> A): Raise[E] ?=> A = new ContextFunction1[Raise[E], A] {
override def apply(using r: Raise[E]): A = block(using r)
}
但是,如果我尝试编译它,编译器会给出以下错误:
[error] 213 |}
[error] | ^
[error] | Found: Object with ((in.rcard.raise4s.Raise[E]) ?=> A) {...}
[error] | Required: A
换成经典就没有错误了
Function1
。
ContextFunction1
不是 Scala API https://docs.scala-lang.org/api/all.html 的一部分,因此不应在源代码中手动使用,尽管它已记录在 https:// /docs.scala-lang.org/scala3/reference/contextual/context-functions-spec.html
即使是普通函数通常也通过 lambda 语法而不是
new
关键字实例化。 new Function1
被编译为 invokespecial
,而 ... => ...
被编译为 invokedynamic
字节码。
通过
?=>
定义隐式函数
def mem[E, A](block: Raise[E] ?=> A): Raise[E] ?=> A = (r: Raise[E]) ?=> block(using r)
def mem[E, A](block: Raise[E] ?=> A): Raise[E] ?=> A = r ?=> block(using r)
def mem[E, A](block: Raise[E] ?=> A): Raise[E] ?=> A = block
在编译器中,
ContextFunctionN
的符号在此处创建:
/** The trait FunctionN and ContextFunctionN for some N
* @param name The name of the trait to be created
*
* FunctionN traits follow this template:
*
* trait FunctionN[-T0,...-T{N-1}, +R] extends Object {
* def apply($x0: T0, ..., $x{N_1}: T{N-1}): R
* }
*
* That is, they follow the template given for Function2..Function22 in the
* standard library, but without `tupled` and `curried` methods and without
* a `toString`.
*
* ContextFunctionN traits follow this template:
*
* trait ContextFunctionN[-T0,...,-T{N-1}, +R] extends Object {
* def apply(using $x0: T0, ..., $x{N_1}: T{N-1}): R
* }
* ImpureXYZFunctionN follow this template:
*
* type ImpureXYZFunctionN[-T0,...,-T{N-1}, +R] = {cap} XYZFunctionN[T0,...,T{N-1}, R]
*/
private def newFunctionNType(name: TypeName): Symbol = {
无法实例化
ContextFunction1
似乎是预期的行为
// `ContextFunctionN` does not have constructors
!ctor.exists || zeroParams(ctor.info)
https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/core/Types.scala#L6011
/** ... check that ... no user-written class extends ContextFunctionN.
*/
def checkParents(cls: Symbol, parentTrees: List[Tree])(using Context): Unit = cls.info match {
...
https://github.com/scala/scala3/blob/main/compiler/src/dotty/tools/dotc/typer/RefChecks.scala#L120
对于
FunctionN
源是为 Scala 2 标准库生成的。对于 ContextFunctionN
甚至没有生成源。