我只是遇到了函数和对象之间的奇怪差异(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 val之间有区别?
更新:显然,二进制函数不会发生问题: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扩展计数作为跃点”,因为我们需要使用_创建方法值)
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
是methods
,与functions
不同。
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>
您可以通过部分应用将
method
转换为function
。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
现在,关于
methods
和functions
之间的区别...您可以在不带括号的情况下调用不带参数的
method
()
...,但在没有()
的情况下不能调用函数。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
methods
与functions
不同的最重要原因之一是,因为Scala的创建者希望与Java无缝无缝互操作,而又不会陷入Java的局限性。因此,
methods
(def
)与Java methods
非常相似,并且保持functions
与methods
不同,使他们可以自由地自由创建Scala(他们想要的方式)。另外...另一个主要区别是
methods
可以接受Type-classes
,而functions
不能接受。基本上你可以有通用的methods
像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()
关于scala - Scala中的def/lambda隐式转换?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28450337/