scala - def 是否被视为 Scala 中的闭包?

标签 scala function closures

我想了解声明为 val 的闭包与声明为方法(使用 def 关键字)的闭包之间的区别。这两个函数之间到底有什么区别,ep 方法是闭包吗?

scala > var more=10

scala > val phi= (x:Int)=>x+more

scala > def ep(x:Int):Int= x+more

最佳答案

一个捕获自由变量的函数对象,据说是 “关闭” 在创建变量时可见的变量称为关闭。例如:

var foo = 10
val bar = (x:Int) => x+foo

这里,foo 是函数字面量中的自由变量,因此函数字面量是开放项。因此,val bar 是一个闭包,因为函数值(对象)是用开放项 foo 创建的。

现在,让我们从valdef在函数定义方面的区别开始。

In scala, function is a value and you can assign it to variable.

当你用 val 定义一个函数时,你是用一个函数字面量来定义它的 val bar = (x:Int) => x+foo,它 < strong>返回一个函数对象并将其作为值赋给bar。在 val 的情况下,函数值按定义计算。这意味着,函数文字 (x:Int) => x+foo 被评估为具有自由变量 foo 的函数值,并存储在 bar 中变量作为闭包

//In the following snippet, a function literal is evaluated to object Function1 and assigned to val bar. 
scala> var foo = 10
foo: Int = 10

scala> val bar = (x: Int) => x + foo
bar: Int => Int = <function1>         //Function1 object is returned

由于 bar 是一个值,并且按其定义进行计算,因此无论何时访问,它都将始终引用内存中的同一对象。

scala> bar eq bar       //because both instance refer to same instance. 
res11: Boolean = true

另一方面,您使用 def 定义了一个方法,而方法不是 Scala 中的函数。根据 Scala 语言规范,method do not have type in Scala hence it cannot be used as value . 例如,您不能这样做:

val bar = {def foo(x:Int): Int = x + 1 }

但是,根据规范,如果方法名称用作值,则 Scala 隐式转换它为相应的函数类型 ETA Expression .例如方法 def a: Int 被转换为 a: => Int。这意味着,每次您调用方法时,它都会返回一个函数值

scala> def foo():Int = 1
a: ()Int

scala> val bar:( ()=> Int) = foo
bar: () => Int = <function0>        //foo return Function0

//Note, val bar = foo, will assign the value returned by foo instead of returning function, so specify type. 

因此,方法可以用作函数。例如,当某些方法或函数需要函数类型作为参数时,您可以提供 def 方法。

scala> val foo = (x:Int, double:Function1[Int, Int]) => double(x)
foo: (Int, Int => Int) => Int = <function2>

scala> def double(x:Int):Int = x * 2
double: (x: Int)Int

scala> foo(3, double)
res1: Int = 6

此外,请注意,使用方法时,每次调用都会获得一个新函数。

scala> def double: Int => Int = _ * 2
double: Int => Int

scala> double eq double
res15: Boolean = false      //false because every time double refers to new instance and hence is not equal unlike val. 

现在,让我们结束吧。valdef 方法定义的函数文字都返回函数值(对象)。在运行时从函数字面量创建的函数值(对象)是闭包。另一方面,方法不是闭包,但是通过调用方法获得的函数值是闭包。

scala> var more = 1
more: Int = 1

scala> val foo = (x:Int) => x + more    // foo is clouser.
foo: Int => Int = <function1>

scala> def bar(x:Int):Int = x + more    // bar is not clouser.
bar: (x: Int)Int

scala> val barClouser : (Int => Int) = bar  // barClouser is clouser. 
barClouser: Int => Int = <function1>

scala> val barValue = bar(3)    // bar is converted to clouser and then clouser value is evaluated and result is assigned to barValue variable. 
barValue: Int = 4   

scala> val fooValue = foo(3)    //foo value is evaluated and returned as value which is assigned to fooValue variable. 
fooValue: Int = 4

关于scala - def 是否被视为 Scala 中的闭包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45771686/

相关文章:

c++ - 调用非静态函数作为谓词?

javascript - 我可以使用原型(prototype)模式而不是闭包模式来创建解析为对象的 promise 吗?

javascript - 如何循环 Angular FormArray - 当前设置为循环中的最后一项

javascript - 事件函数问题

c - 姓名和姓氏搜索功能将无法使用。为什么?

JavaScript 的匿名对象原型(prototype)

scala - sbt 忽略我的 scaladoc 设置

scala - 避免 Scala 中的全局状态

Scala 默认设置实现

scala - Sbt - 指定依赖扩展