函数文字-需要帮助理解代码片段



我基本上是函数式编程和scala的新手,下面的问题可能看起来很愚蠢。

val f = (a:Int) => a+1

在上面的片段中,我应该将f视为函数还是变量?来自C/C++背景,首先想到的是f是一个存储匿名函数返回值的变量,但我认为这不是正确的解释方式。任何解释都会非常有用。

(关于scala/函数式编程,我上面使用的一些术语可能是错误的,请耐心等待)

这里,f是一个存储函数的变量。这与说以下任何一句话都没有什么不同:

val a = 4               // `a` is a variable storing an Int
val b = "hi"            // `b` is a variable storing a String
val f = (a:Int) => a+1  // `f` is a variable storing a function

你也可以用REPL:来确认这一点

scala> val f = (a:Int) => a+1
f: Int => Int = <function1>

这告诉你f的类型是Int => Int。换句话说,f是一个接受一个参数Int并返回Int的函数。

由于f是一个变量,您可以对其调用方法,也可以将其作为参数传递给期望其类型的函数:

a + 3  // here I'm calling the `+` method on `a`, which is an Int
f(3)   // here I'm calling the `apply` method on `f`, which is a function `Int => Int`
f(a)   // the function `f` expects an `Int`, which `a` is
(1 to 3).map(f)  // the `map` method expects a function from Int to Int, like `f`

是的,就像dhg所说的,f是一个存储函数的变量(不能更改)。

然而,这里有一个微妙之处:

。。。首先想到的是f是一个变量,它存储匿名函数的返回值

f实际上存储函数,而不是结果。所以你可以给它不同的输入,得到不同的输出。因此,您可以像使用f(7)f(5)一样使用它。Scala中的函数是对象,因此可以分配给变量、作为参数传递等。

我最近发布了关于函数文字的文章,这可能对您有所帮助。

f是表示函数文字的值。

在语句中,右侧是一个函数文字。左手边将其绑定到一个名称上,然后称为(val关键字类似于LISP中的let)。现在该函数与符号f相关联,因此可以使用该符号f来引用该函数。

我不同意其他的答案,即f应该被称为一个变量。f是一个值,因为它固定在右侧项上,该项仅确定一次,并且不能更改。相反,var引入的变量允许您重新为符号赋值:

var f = (i: Int) => i + 1

其中,var开始变量定义,f是变量的名称或符号,可以有一个可选的: ...定义变量的类型(如果忽略了这一点,则类型将自动从赋值中推断出来),= ...定义最初分配给变量的值

因此,当说时,不要将其与数字常量混淆,它只是一个不变的实体。函数也可以是一个值,因为f总是表示同一个相同的函数,即使你可以为该函数提供不同的参数,从而产生不同的结果。

现在使用var,您可以重新分配其右侧:

f(2) // --> 3
f = (i: Int) => i * 2 // assign a new function to the variable f.
f(2) // --> 4

函数式编程就是要避免变量(重新赋值)。


也可以定义一个函数,而不将其赋值(值或变量)。以下定义了这样一个函数,并立即用参数4:调用它

{ i: Int => i + 1 } apply 4 // --> 5

尽管这作为一个语句本身很少有用,但在调用需要函数参数的方法时,您会经常看到"普通"函数。例如

val s = List(1, 2, 3)
s.map { (i: Int) => i + 1 } // --> List(2, 3, 4)
s.map { _ + 1 }             // equivalent
s.map( _ + 1 )              // equivalent

相关内容

最新更新