curriable 函数,returns scala 中的函数通过'=>',和(其次)通过 1 arg list 后跟另一个

curriable function that returns a function in scala via '=>', and (secondly), via 1 arg list followed by another

我开始学习一点 Scala,基本上 了解 return 函数和柯里化函数,但是 我已经看到了执行此操作的两种语法,我想更好 了解差异,也许还有一些背后的理论 怎么回事。

在第一种方法中(使用=>)我可以通过指定 要绑定到变量 x 的参数。但是当我尝试这样做时 使用第二种方法,编译器告诉我需要指定 _ 第二个参数的通配符。

我明白我需要做什么,但我不确定为什么我需要做 事情是这样的。有人可以告诉我 Scala 编译器是什么吗 在这里做什么?

第一种方法使用 =>

def add(x:Int) = (y:Int) => x + (-y)
add: (x: Int)Int => Int

scala> def adder = add(100)   // x is bound to 100 in the returned closure
adder: Int => Int

scala> adder(1)
res42: Int = 99

第二种方法使用一个 arg 列表后跟另一个

scala> def add2(x:Int)(y:Int) :  Int =  x + y
add2: (x: Int)(y: Int)Int

scala> def  adder2 = add2(100)
<console>:9: error: missing arguments for method add2;
follow this method with `_' if you want to treat it 
 as a partially applied function

       def  adder2 = add2(100)
                         ^

scala> def  adder2 = add2(100) _    // Okay, here is the '_'
adder2: Int => Int

scala> adder2(1)                    // Now i can call the curried function
res43: Int = 101

您看到的是 方法类型 函数类型 之间的区别。这是一个微妙的、有时令人困惑的区别。 This answer 包含对方法类型和函数类型之间差异的非常全面的解释。以下是与您的问题最相关的一些要点:

A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library.

A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type... A method type is a def declaration - everything about a def except its body.

你不能直接分配一个方法做 val:

def foo(x: Int) = x
val myFooVal = foo //does not compile   

eta-expansion的过程可以将方法转化为函数,可以赋值给一个val:

val myFooVal = foo _

Here 是一个更深入地探讨 eta 扩展的博客 post。

您的示例中有趣的是您将方法与函数混合在一起。这完全没问题,但这可能是您在这里感到困惑的一部分:

def add(x:Int) = (y:Int) => x + (-y)

这是方法 returns 一个函数,而这个:

def add2(x:Int)(y:Int) =  x + y

是一个纯方法,与所有方法一样,可以使用 eta-expansion 转换为函数类型:

add2 _ //Int => (Int => Int)
add2(2) _ //Int => Int

在 REPL 中尝试一下,看看 Scala 如何以不同的方式处理这些类型可能会有所启发:

def add(x:Int) = (y:Int) => x + (-y)
//add: (x: Int)Int => Int

def add2(x:Int)(y:Int) =  x + y
//add2: (x: Int)(y: Int)Int

注意这里 REPL 的打印输出有何不同。在第一个例子中,我们可以看到 add 是一个 returns 类型 Int => Int 的方法,它是一个函数。在第二个示例中,方法语法通过第二个参数保留。