在函数应用程序中找不到隐式参数

时间:2011-02-22 00:39:51

标签: function scala implicit-conversion

如果我定义的打印功能仅将数字设为:

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 =&gt;中找到隐式转换。 java.lang.Integer中。

如何重新定义打印,使其返回功能并以正确的方式访问含义?

1 个答案:

答案 0 :(得分:5)

这里的问题是您将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返回的函数参数来帮助进行类型推断。