如果我定义的打印功能仅将数字设为:
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中。
如何重新定义打印,使其返回功能并以正确的方式访问含义?
答案 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
返回的函数参数来帮助进行类型推断。