2012-09-21 134 views
1

我基本上是新功能编程和scala,下面的问题可能看起来很愚蠢。函数文字 - 需要帮助理解代码片段

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

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

(一些我上面使用可能是错相对于阶/功能编程,术语的麻烦与它承担)

回答

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` 
+0

不要说“变量”,这很混乱。这是一个价值,你不能用任何新的价值来覆盖它。术语“变量”应该保留为“var”,值应该用于“val”。它只是一个__place-holder__意义上的变量,这可能就是你的意思。 –

+2

@ 0__:Scala规范使用单词“变量”,即使值无法更改,Haskell规范也是如此,几乎所有的数学教科书都是如此,等等。您可能认为标准用法可能会引起混淆,但尝试改变它不是一场你将要赢得的战斗。 –

+0

@Travis,同意。 – dhg

1

是的,像DHG说,f是一个变量(即可以”不能改变)存储一个函数。

但是,这里有一个细微之处:

...出现的第一个念头是,f是存储的匿名函数的 返回值

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

I recently posted about function literals,这可能对您有所帮助。

0

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 
+0

带上一粒盐;正如在上面的评论中提到的那样,即使在文献中,'val'和'var'通常都被称为变量,可能使用“一次写入”或“不变变量”来区分前者和后者。 –