gpt4 book ai didi

scala - Scala中defs/lambdas的隐式转换?

转载 作者:行者123 更新时间:2023-12-04 08:43:25 26 4
gpt4 key购买 nike

我刚刚遇到了函数和对象之间的奇怪差异(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

同样,空函数也不会造成问题:
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

所以,换个说法:为什么这不适用于一元方法和函数?

更新:问题似乎也与目标类型(f 的参数 h 的类型)有关。以下也有效(这次,赞成“eta-expansion counts as hop”,因为我们需要从 using _ 创建一个方法值)
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

最佳答案

在斯卡拉 defsmethodsfunctions 不同.

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>

您可以转换 methodfunction通过部分应用它。
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中defs/lambdas的隐式转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28450337/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com