我基本上是函数式编程和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