我基本上不熟悉函数式编程和scala,以下问题可能看起来很愚蠢。
val f = (a:Int) => a+1
在上面的代码片段中,我应该将f
视为函数还是变量?来自C / C ++背景,首先想到的是f
是一个存储匿名函数返回值的变量,但我认为这不是解释它的正确方法任何解释都会有所帮助
(我在上面使用的一些术语在scala /函数式编程方面可能是错误的,请小心使用它)
答案 0 :(得分:5)
这里,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`
答案 1 :(得分:1)
是的,就像dhg所说,f
是一个存储函数的变量(无法更改)。
然而,这里有一个微妙的地方:
......首先想到的是f是一个存储的变量 匿名函数的返回值
f
实际上存储了函数,而不是结果。因此,您可以为其提供不同的输入,并获得不同的输出。因此,您可以使用f(7)
,然后f(5)
。 Scala中的函数是对象,因此可以分配给变量,作为参数传递等。
I recently posted about function literals,这可能会对您有所帮助。
答案 2 :(得分:0)
f
是一个值,表示函数文字。
在声明中,右侧是函数文字。左侧将其绑定到名称,然后将其命名为值(val
关键字与LISP中的let
类似)。现在该函数与符号f
相关联,因此您可以使用此符号f
来引用该函数。
我不同意其他答案,这些答案表明f
应该被称为变量。 f
是一个值,因为它固定在右侧的术语中,该术语仅确定且无法更改。相反,使用var
引入的变量允许您为符号重新赋值:
var f = (i: Int) => i + 1
var
开始变量定义,f
是变量的名称或符号,可以有一个可选的: ...
定义变量类型(如果你把它留下来,从分配中自动推断出类型),= ...
定义分配给变量的最初值。
因此,当一个人说 value 时,不要将其与数字常量混淆,它只是一个实体,不会改变。函数也可以是一个值,因为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