在Scala中,您可以执行以下操作:
def foo(implicit v: Int) = println(v);
def h(x: Int) = { implicit val i: Int = x; foo }
h(42)
> 42
h
调用将foo
引用作为闭包。
尝试将foo
传递给h
作为参数并不奇怪:
def g(x: Int)(f: Int => Unit) = { implicit val i: Int = x; f }
但它不会起作用:
g(1)(foo)
> error: could not find implicit value for parameter v: Int
我认为它发生的是foo
被称为对实际参数的评估。 是吗?
当传递具有普通参数列表的函数(非隐式)时,不会评估该函数:
def foo2(v: Int) = println("Foo2")
g(1)(foo2)
> Int => Unit = <function1>
这是一个预期的结果,foo2
评估不会作为实际参数的评估。
当没有隐含值可用时,为什么foo
被评估为实际参数?
分配也是如此:
val fooref: Int => Unit = foo
> error: could not find implicit value for parameter v: Int
由于Int => Unit
与Int
参数被标记为隐式的函数不匹配,编译器会将其作为有效的实际参数丢弃,因此会尝试对其进行评估。找不到声明的隐含值来完成调用。
如果是这种情况,用隐式参数表达函数类型的方式是什么?
答案 0 :(得分:11)
不幸的是,函数不能有隐式参数 - 只有方法可以。
在表达式g(1)(foo)
中,foo
从方法转换为函数(也称为eta-expansion)。并且Scala规范的section 6.26.2声明隐式参数在 eta-expansion之前应用。
查看此票证:implicit methods behave suboptimally when used non-implicitly
答案 1 :(得分:1)
f
函数的g
参数类型为Function1[Int, Unit]
。 Function1[A, B]
是使用单一方法apply(a: A): B
的特征,其中a
不是隐式的。因此,您无法从Function1[Int, Unit]
创建foo
的实例 - 它不会拥有正确的签名。