我一直被一个类型推断问题困扰着,我不确定我是否做错了什么,编译器中是否有一个bug,或者是语言上的一个限制
我已经创建了一个虚拟的例子来说明这个问题,用例没有意义,但是相信我,我有一个有效的用例
假设我有这个密码
val function: (Int, String) => String = (_, _) => ""
implicit class Function2Ops[P1, P2, R](f: (P1, P2) => R) {
def printArgs(p1: P1, p2: P2): Unit = println(p1, p2)
}
function.printArgs(1, "foo")
它可以工作和打印
(1,foo)
现在,如果我将代码改为(注意by name参数)
val function: (Int, => String) => String = (_, _) => ""
implicit class Function2Ops[P1, P2, R](f: (P1, P2) => R) {
def printArgs(p1: P1, p2: P2): Unit = println(p1, p2)
}
function.printArgs(1, "foo")
(1,MyTest$$Lambda$131/192881625@61d47554)
现在,我可以尝试模式匹配和/或使用TypeTag提取值,以防是by name参数,但是,
我真正想做的就是做这样的事
trait Formatter[T] {
def format: String
}
case class ReverseStringFormat(v: String) extends Formatter[String] {
override def format: String = v.reverse
}
case class PlusFortyOneFormat(v: Int) extends Formatter[Int] {
override def format: String = (v + 41).toString
}
implicit def noOpFormatter[T](v: T): Formatter[T] = new Formatter[T] {
override def format: String = v.toString
}
val function: (Int, => String) => String = (_, _) => ""
implicit class Function2Ops[P1, P2, R](f: (P1, P2) => R) {
def printArgs(p1: Formatter[P1], p2: Formatter[P2]): Unit = println( p1.format, p2.format)
}
function.printArgs(1, ReverseStringFormat("foo"))
Formatter[TypeOfOriginalParam]
这也是为什么我
implicit def noOpFormatter[T](v: T): Formatter[T]
当我不需要任何格式的时候
Error:(22, 40) type mismatch;
found : ReverseStringFormat
required: Formatter[=> String]
function.printArgs(1, ReverseStringFormat("foo"))
val function: (Int, => String) => String = (_, _) => ""
implicit class Function2Ops[P1, P2, R](f: (P1, => P2) => R) {
def printArgs(p1: Formatter[P1], p2: Formatter[P2]): Unit = println( p1.format, p2.format)
}
function.printArgs(1, ReverseStringFormat("foo"))
(1,oof)
现在,主要的问题是我想对任何函数这样做,不管它的参数是按值还是按名称。
有什么想法吗?如果我只对类型感兴趣,我真的需要关心争论的懒散性吗?我是想做一些设计不支持的事情,还是编译器中有一个bug?
顺便说一句,这是我想避免的
val function: (Int, => String) => String = (_, _) => ""
val function2: (Int, String) => String = (_, _) => ""
val function3: (=> Int, String) => String = (_, _) => ""
val function4: (=> Int, => String) => String = (_, _) => ""
implicit class Function2Ops[P1, P2, R](f: (P1, => P2) => R) {
def printArgs(p1: Formatter[P1], p2: Formatter[P2]): Unit = println("f1", p1.format, p2.format)
}
implicit class Function2Opss[P1, P2, R](f: (P1, P2) => R) {
def printArgs(p1: Formatter[P1], p2: Formatter[P2]): Unit = println("f2", p1.format, p2.format)
}
implicit class Function2Opsss[P1, P2, R](f: (=> P1, P2) => R) {
def printArgs(p1: Formatter[P1], p2: Formatter[P2]): Unit = println("f3", p1.format, p2.format)
}
implicit class Function2Opssss[P1, P2, R](f: (=> P1, => P2) => R) {
def printArgs(p1: Formatter[P1], p2: Formatter[P2]): Unit = println("f4", p1.format, p2.format)
}
function.printArgs(1, "foo")
function2.printArgs(1, ReverseStringFormat("foo"))
function3.printArgs(1, "foo")
function4.printArgs(PlusFortyOneFormat(1), "foo")
它的工作原理(注意,我随机使用了格式化程序或原始值,不管原始参数是按名称还是按值)
(f1,1,foo)
(f2,1,oof)
(f3,1,foo)
(f4,42,foo)
但把这些都写给我似乎太奇怪了