Scala中defs / lambdas的隐式转换?
我刚刚遇到函数和对象之间的奇怪差异(
scala 2.10):
implicit def conv(c: Int => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v)) def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1) def a(x: Int) = x.toString val b = (x: Int) => x.toString // def main(args: Array[String]) = f(a) // fail // def main(args: Array[String]) = f((x: Int) => x.toString) // fail def main(args: Array[String]) = f(b) // ok 为什么defs / lambda文字和lambda vals之间有区别? 更新:显然,二进制函数不会出现问题:Implicit conversion of a function to a second-order-function only works if the function to convert has at least two parameters 我检查过这个,确实以下代码有效: implicit def conv(c: (Int,Unit) => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v,())) def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1) def a(x: Int,y : Unit) = x.toString val b = (x: Int,y : Unit) => x.toString def main(args: Array[String]) = f(a) // ok def main(args: Array[String]) = f((x: Int,y: Unit) => x.toString) // ok def main(args: Array[String]) = f(b) // ok 同样,Nullary函数也不会造成问题: implicit def conv(c: () => String) : (PrintStream => Int => Unit) = p => v => p.println(c()) def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1) def a() = "1" val b = () => "1" def main(args: Array[String]) = f(a) // ok def main(args: Array[String]) = f(() => "1") // ok def main(args: Array[String]) = f(b) // ok 所以,改写一下这个问题:为什么这对UNARY方法和函数不起作用? 更新:问题似乎也与目标类型(f的参数h的类型)有关.以下也有效(这次,支持“eta-expansion计为跳数”,因为我们需要从使用_创建方法值) implicit def conv(c: Int => String) : Unit = () def f(h: Unit) : Unit = System.out.print("?") def a(x: Int) = x.toString val b = (x: Int) => x.toString def main(args: Array[String]) = f(a _) // ok def main(args: Array[String]) = f((x: Int) => x.toString) // ok def main(args: Array[String]) = f(b) // ok 解决方法
在scala中,defs是方法,与函数不同.
scala> def a( x: Int,y: Int ): Int = x + y a: (x: Int,y:Int)Int scala> (x: Int,y: Int) => x + y res0: (Int,Int) => Int = <function2> 您可以通过部分应用将方法转换为函数. scala> b _ res1: (Int,Int) => Int = <function2> 那么..你可以做到, implicit def conv(c: Int => String) : (PrintStream => Int => Unit) = p => v => p.println(c(v)) def f(h: PrintStream => Int => Unit) : Unit = h(System.out)(1) def a(x: Int) = x.toString val af = a _ def main( args: Array[ String ] ) = f( af ) 另外,正如@ srgfed01在他的评论中提到的…对于第二种情况,问题是……如果你正确指定类型,它们的类型没有明确指定……第二种情况就可以了. scala> f( ( a => a.toString ): (Int => String) ) 1 要么 scala> f( ( _.toString ): (Int => String) ) 1 现在,关于方法和功能之间的差异…… 你可以在没有括号()的情况下调用不带参数的方法……但是你不能在没有()的情况下调用函数. scala> def g() = 5 g: ()Int scala> g res15: Int = 5 scala> () => 5 res13: () => Int = <function0> scala> res13 res14: () => Int = <function0> scala> res13() res15: 5 方法与函数不同的最重要原因之一是因为Scala的创建者希望与Java无缝互操作,而不会受到Java的限制. 因此,方法(def)与Java方法非常相似,并且保持与方法不同的函数使得它们能够以他们想要的方式创建Scala的无限自由. 另外……另一个主要区别是方法可以接受Type-classes,而函数则不能.基本上你可以有像.这样的通用方法 scala> :paste trait Behave { def behave } class A( elem: String ) extends Behave { def behave() { println( elem ) } } // Exiting paste mode,now interpreting. defined trait Behave defined class A 现在您可以定义一个通用方法, scala> def check[ T <: Behave ]( t: T ): Unit = t.behave() check: [T <: Behave](t: T)Unit 但是你不能定义这样的函数, scala> ( t: T ) => t.behave() <console>:8: error: not found: type T ( t: T ) => t.behave() 或者像这样 scala> ( t: (T <: Behave) ) => t.behave() <console>:1: error: ')' expected but '<:' found. ( t: (T <: A) ) => t.behave() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |