为什么隐式参数与非隐式参数结合时不起作用
Why implicit parameter not working when combined with non implicit parameter
一个非常简单的用例,假设我有一个 class Foo
接受 2 个参数,1 个是普通参数,1 个是隐式参数。
class Foo(val msg: String, implicit val n: Int) {
def multiplier = msg * n
}
implicit val num: Int = 4
val foo = new Foo("yo")
println(foo.msg)
我知道如果我将隐式参数移动到另一个列表即 curried class Foo(val msg: String)(implicit val n: Int)
它将起作用。但是可以说出于某种原因我不想那样做。
有人可以解释为什么当前版本的实现不起作用吗?
语言规范是这样写的。您必须在单独的参数列表中定义。语言规范根本不讲隐式参数,只讲一个隐式参数列表:
An implicit parameter list (implicit p1,…,pn)
of a method marks the parameters p1
,…,pn
as implicit. A method or constructor can have only one implicit parameter list, and it must be the last parameter list given.
也许可以在邮件列表存档或其他地方检查是否存在某种原因。
我们cannot mix implicit and non-implicit formal parameters within a single parameter list because implicit
modifier is a property of the list,不是参数。因此下面的方法定义是非法的
def foo(msg: String, implicit n: Int) = ??? // Error
然而为什么以下是合法的
class Foo(val msg: String, implicit val n: Int) // OK
在声明 class 构造函数时,在单个参数子句中混合隐式和非隐式参数似乎是合法的,但是 implicit
修饰符 不 应用于形式参数 n
但它正在修改相应的自动生成的访问器 。因为我们已经声明 n
为 val
这扩展为
class Foo {
...
implicit def n(): Int = n;
def <init>(msg: String, n: Int) = { // note how msg and n are *NOT* implicit
...
}
}
并且将成员声明为隐式是完全合法的。另一方面,如果我们删除 val
声明,从而不声明成员,我们会看到它不会编译
class Foo(val msg: String, implicit n: Int) // Error: 'val' expected but identifier found ^
类似于它在方法定义中是非法的。因此以下不编译的原因
implicit val num: Int = 4
new Foo("yo") // error: unspecified value parameter n
是因为形参n
实际上不是隐式。
附带说明,以下 Scala 2 要求
A method or constructor can have only one implicit parameter list, and
it must be the last parameter list given.
已被 Scala 3 改变Multiple Given Clauses
There can be several given parameter clauses in a definition and
given parameter clauses can be freely mixed with normal ones.
Example:
def f(u: Universe)(given ctx: u.Context)(given s: ctx.Symbol, k: ctx.Kind) = ...
其中 given
到 implicit
.
一个非常简单的用例,假设我有一个 class Foo
接受 2 个参数,1 个是普通参数,1 个是隐式参数。
class Foo(val msg: String, implicit val n: Int) {
def multiplier = msg * n
}
implicit val num: Int = 4
val foo = new Foo("yo")
println(foo.msg)
我知道如果我将隐式参数移动到另一个列表即 curried class Foo(val msg: String)(implicit val n: Int)
它将起作用。但是可以说出于某种原因我不想那样做。
有人可以解释为什么当前版本的实现不起作用吗?
语言规范是这样写的。您必须在单独的参数列表中定义。语言规范根本不讲隐式参数,只讲一个隐式参数列表:
An implicit parameter list
(implicit p1,…,pn)
of a method marks the parametersp1
,…,pn
as implicit. A method or constructor can have only one implicit parameter list, and it must be the last parameter list given.
也许可以在邮件列表存档或其他地方检查是否存在某种原因。
我们cannot mix implicit and non-implicit formal parameters within a single parameter list because implicit
modifier is a property of the list,不是参数。因此下面的方法定义是非法的
def foo(msg: String, implicit n: Int) = ??? // Error
然而为什么以下是合法的
class Foo(val msg: String, implicit val n: Int) // OK
在声明 class 构造函数时,在单个参数子句中混合隐式和非隐式参数似乎是合法的,但是 implicit
修饰符 不 应用于形式参数 n
但它正在修改相应的自动生成的访问器 n
为 val
这扩展为
class Foo {
...
implicit def n(): Int = n;
def <init>(msg: String, n: Int) = { // note how msg and n are *NOT* implicit
...
}
}
并且将成员声明为隐式是完全合法的。另一方面,如果我们删除 val
声明,从而不声明成员,我们会看到它不会编译
class Foo(val msg: String, implicit n: Int) // Error: 'val' expected but identifier found ^
类似于它在方法定义中是非法的。因此以下不编译的原因
implicit val num: Int = 4
new Foo("yo") // error: unspecified value parameter n
是因为形参n
实际上不是隐式。
附带说明,以下 Scala 2 要求
A method or constructor can have only one implicit parameter list, and it must be the last parameter list given.
已被 Scala 3 改变Multiple Given Clauses
There can be several given parameter clauses in a definition and given parameter clauses can be freely mixed with normal ones. Example:
def f(u: Universe)(given ctx: u.Context)(given s: ctx.Symbol, k: ctx.Kind) = ...
其中 given
implicit
.