首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >def在Scala中被认为是一个闭包吗?

def在Scala中被认为是一个闭包吗?
EN

Stack Overflow用户
提问于 2017-08-19 12:43:32
回答 1查看 716关注 0票数 3

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

scala > var more=10

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

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-20 13:39:23

一个函数对象捕获空闲变量,并在创建时可见的变量上被称为“关闭”,称为闭包。例如:

代码语言:javascript
复制
var foo = 10
val bar = (x:Int) => x+foo

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

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

在scala中,函数是一个值,您可以将它赋值给变量。

当您用val定义函数时,您是用一个函数文字定义它为val bar = (x:Int) => x+foo返回一个函数对象并将它赋值给bar。在val的情况下,函数值是根据定义的值计算的。这意味着,函数文本(x:Int) => x+foo被计算为使用空闲变量foo的函数值,并以闭包的形式存储在bar变量中。

代码语言:javascript
复制
//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是一个值,并且是在定义时计算的,因此每当访问它时,它都会引用内存中的同一个对象。

代码语言:javascript
复制
scala> bar eq bar       //because both instance refer to same instance. 
res11: Boolean = true

另一方面,您使用def定义了一个方法,而方法不是Scala中的一个函数。根据Scala语言规范,方法在Scala中没有类型,因此不能用作值。。例如,您不能这样做:

代码语言:javascript
复制
val bar = {def foo(x:Int): Int = x + 1 }

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

代码语言:javascript
复制
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方法。

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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方法定义的函数文本返回函数值(object)。从函数文字在运行时创建的函数值(对象)是闭包。另一方面,方法不是闭包,但是从调用方法得到的函数值是闭包。

代码语言:javascript
复制
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
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45771686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档