如果我定义一个仅接受数字的打印函数:
def print[T <% Number](value:T) {}
print: [T](value: T)(implicit evidence$1: (T) => java.lang.Number)Unit
我可以通过以下方式调用上面的内容:
print(5)
print(5.5)
print(6L)
但不能使用字符串:
print("aaa")
<console>:7: error: could not find implicit value for evidence parameter of type (java.lang.String) => java.lang.Number
print("aaa")
这是预期的。
但是如果我将打印函数定义为:
def print2[T <% Number]: T => Unit = value => { }
print2: [T](implicit evidence$1: (T) => java.lang.Number)(T) => Unit
注意隐式参数是第一个参数而不是最后一个。
如果我尝试手动定义上述函数:
def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit = { }
<console>:1: error: '=' expected but '(' found.
def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit = { }
基本上,上面不是一个有效的函数定义,但编译器在我之前定义 print2 时创建了它。
当我用 Int 调用 print2 时:
print2(5)
<console>:7: error: type mismatch;
found : Int(5)
required: (?) => java.lang.Number
print2(5)
如果我参数化它:
print2[Int](5)
<console>:7: error: type mismatch;
found : Int(5)
required: (Int) => java.lang.Number
print2[Int](5)
看起来找不到 scala.Int => java.lang.Integer 的隐式转换。
如何重新定义 print 以便它返回函数并以正确的方式访问隐式?
最佳答案
这里的问题是您将 5 作为隐式参数传递。
现在我在计算机上,进行一些更正:
def print[T <% Number](value:T) {}
你称其为函数,但它是一个方法。
def print2[T <% Number]: T => Unit = value => { }
同样,您将其称为函数。实际上,它是一个方法,返回一个函数。该方法接收一个类型参数 T
和一个隐式参数。
print2(5)
因此,在这里,您调用方法 print2
,并将 5
作为其隐式参数。尚未推断类型 T
,因为它首先尝试使 5
符合预期类型 T => Number
。但是,由于 5
不符合 Function1[T, Number]
,因此即使没有推断 T
,它也会失败。
调用print2
的方法有很多种。例如:
print2(implicitly[Int => Number])
print2[Int]
(print2: Int => Unit)
val f: Int => Unit = print2
但是,要调用 print2
返回的函数,您必须避免使 (5)
看起来像方法 print2< 的隐式参数
。实际上上面只有一种情况需要不同的东西:
print2(implicitly[Int => Number])(5)
print2[Int].apply(5)
(print2: Int => Unit)(5)
val f: Int => Unit = print2; f(5)
现在,大多数示例都具有显式类型参数,而不是推断类型参数。让我们考虑一下如果没有它会发生什么:
print2.apply(5)
由于没有参数传递给 print2
,因此它选择符合 T
边界的最具体类型。由于 T
没有界限,因此选择 Nothing
。然后,它尝试找到隐式的 Nothing => Unit
。因为没有这样的隐式,所以它失败了。
永远不会考虑 print2
返回的函数参数来帮助类型推断。
关于function - 函数应用程序中未找到隐式参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5072896/