当scala函数名本身不是函数值时,为什么可以在需要函数值的地方使用它? def(x:Int):布尔=(x>=0&&xf(x)

当scala函数名本身不是函数值时,为什么可以在需要函数值的地方使用它? def(x:Int):布尔=(x>=0&&xf(x),scala,lambda,wildcard,implicit-conversion,eta-expansion,Scala,Lambda,Wildcard,Implicit Conversion,Eta Expansion,为什么f可以用于预期函数值的地方,即使它本身不是函数值?发生了什么 在需要函数类型的地方,f被转换为匿名函数(x:Int)=>f(x) 为什么f被接受为函数值 map需要一个函数类型,因为ff和g的当前版本和非当前版本都是相同的,所以自动转换是有意义的 另一个优点是map(f)的外观比map(f()))干净 所有为你做的自动和语法糖的缺点是,它可能会令人困惑 请注意,将方法转换为函数的过程称为eta扩展。谢谢,这是问题的核心。通常,在我的思维中,我也会因为同样的原因而陷入困境:我不知道编译器做

为什么
f
可以用于预期函数值的地方,即使它本身不是函数值?

发生了什么

在需要函数类型的地方,
f
被转换为匿名函数
(x:Int)=>f(x)

为什么
f
被接受为函数值

  • map
    需要一个函数类型,因为
    f
    f
    g
    的当前版本和非当前版本都是相同的,所以自动转换是有意义的
  • 另一个优点是
    map(f)
    的外观比
    map(f()))
    干净
  • 所有为你做的自动和语法糖的缺点是,它可能会令人困惑

请注意,将方法转换为函数的过程称为
eta扩展
。谢谢,这是问题的核心。通常,在我的思维中,我也会因为同样的原因而陷入困境:我不知道编译器做什么。如果我想进入下一个层次,我认为是时候更仔细地研究一下编译器这个话题了。学究式的,这不是一个常用的函数,它只是一个函数值而不是一个方法。curried函数是将一个具有多个参数的函数转换为一组嵌套的HOF的结果。@colorblind“如果我想进入下一个层次,我认为是时候更仔细地研究编译器主题了”我不这么认为。您真的不需要知道编译器做什么以及如何做。你通常只需要知道它的一些技巧/语法糖/规则。例如,在本例中,只要知道编译器将把一个方法转换为预期的函数,就足以继续学习。@colorblind您还可以打印出不同的编译器,例如,
scala-Xprint:typer foo.scala
。您甚至可以在REPL
:settings-Xprint:typer
内部实时执行此操作。现在,在输入一些Scala源代码之后,它将打印出阶段。您甚至可以通过
:javap-
看到字节码。您还可以使用
scala-Xprint:typer-e“for{i2}生成{i.toString}”
def f(x: Int): Boolean = (x >= 0 && x < 4)

List(1, 3, 5).map(f)  // List(true, true, false)
f                     // does not compile
def f(x: Int): Boolean = (x >= 0 && x < 4)
// f                    // f itself is not a function value
f(_)                    // f(_) is an anonymous function
List(1, 3, 5).map(f)    // f is converted to f(_) in places where a function type is expected
List(1, 3, 5).map(f(_)) // equivalent to last line
val g = (x: Int) => (x >= 0 && x < 4)
g