我一直坚持使用类型推断问题而且我不确定我是否做错了,编译器中存在错误,或者它是对语言的限制
我创建了一个虚拟示例来显示问题,用例没有意义,但请相信我,我有一个有效的用例
假设我有这个代码
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)
现在,如果我更改代码(注意副名称参数)
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来提取值,以防万一是一个名字参数,但是,我实际上想要实现的是做这样的事情
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)
现在,主要问题是我想为任何函数执行此操作,无论其任何参数是按值还是按名称.那就是我被困住的地方,我可以为每个可能的副词组合创建不同的隐式类,其中有或不带名字参数但是它不实用,因为我需要为从Function1到Function10的每个函数执行此操作,并且by-name和by-value参数之间可能的组合数量将是巨大的.
有任何想法吗?如果我只对这种类型感兴趣,我真的需要关心论证的懒惰吗?我是否尝试做一些不受设计支持的事情,或者可能是编译器中的错误?
顺便说一句,这是我想要避免的
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)
但是把这一切都写给我似乎有点奇怪