彻底说清楚scala中的闭包和柯里化的概念

坚持说大白话,让问题尽可能的简单易懂!

 

1:前言:

闭包和柯里化是学习scala的过程中以及面试的过程中无法忽视的一道坎,不管你是否重视它,它都存在。笔者之前也是对这些东西云里雾里,因为Java里本身没有闭包这个概念的,接触过JS的同学可能知道闭包的概念,我没有接触过JS里的闭包所以也不敢去做对比,这里就我的一些理解和体会分享给大家。

2:闭包:

文档里的英文是 closure  是关闭的意思,翻译过来是闭包。到底怎么算是关闭了呢?关进去的又是什么呢?

把谁给关进去了?

把函数外部的一个自由变量给关进去了。

val a = 3

def f(x:Int)={
    x + a
}

这里的 a 是个自由便量,这里的f是个函数。可以看到 如果说我们调用函数 f (2) 的话 ,那么我们知道这个计算的结果是依赖于这个自由变量 a 的 ,有人说闭包是改变了作用域,笔者认为欠妥,何为改变作用域?不清楚。

闭包最根本的是什么?

闭包最根本的是改变了  a  的生命周期,这个是最关键的,最本质的。

def f1(x:Int)={
  def f2(y:Int)={
        x+y

}
f2 _

}

在Scala里函数是头等公民,这种嵌套的方式是没问题的。并且函数可以作为返回值。

当我们调用函数 f1(3) 的时候,按道理说,当我们 f(1) 被调用完毕之后按道理来说作为局部变量的 x 因该随之弹栈才对,这里是最关键的地方,但是,x 能弹栈吗?如果弹栈那么这个变量就无法被使用了,但是 但是 f2() 此时引用着它,f2() 还没运行 你说 f2() 能让它弹栈吗?很显然是不会。这个时候 x就被捕获了,其实就是把它关起来了,所以闭包最本质的就是改变了 外部变量的生命周期。

 

3:柯里化

柯里化我刚接触的时候感觉很不可思议。这种语法格式在java里是不敢想的,但是用起来就觉得这个东西其实还是挺方便的。柯里化其实不是什么高深的东西,下面让笔者来拆解一下:

def f1(x:Int)={
  def f2(y:Int)={
        x+y

}
f2 _

}

用的还是上面的那个例子

我们来拆解一下:

我们调用函数 f1(2) 得到的结果是:

val func: Int => Int = f1(2)

func: Int => Int = <function1>

可以清楚的看到 返回的是一个函数。不得不说在scala里对于函数真的很灵活。

那么我们调用 f1(2) 返回的就是 函数 f2  ,我们调用一下f2 这个函数那么就是 :  f1(2)(3)   这里是重点,看出来门道了没?这不就是柯里化的表达方式吗?其实到这里柯里化的遮羞布已经被扯下来了。

其实就是函数的嵌套调用。

我为什么拿同样的一个例子来说明闭包和柯里化呢?

因为他们其实有关联,怎么关联呢?

其实柯里化是离不开闭包的,因为函数的嵌套调用本身就是闭包,你想是不是??? f2 用到了外部的f1 里的变量,这不是闭包吗?

 

今天就先说到这里吧。下次再聊一下,scala里的闭包怎么就导致了spark要进行闭包的清理 。。。。 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值