假如我们定义如下的函数:

(x:Int) => x + more

这里我们引入一个自由变量more.它不是所定义函数的参数,而这个变量定义在函数外面,比如:

var more =1

那么我们有如下的结果:

scala> var more =1
more: Int = 1 scala> val addMore = (x:Int) => x + more
addMore: Int => Int = <function1> scala> addMore (100)
res1: Int = 101

这样定义的函数变量addMore 成为一个“闭包”,因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。有意思的是,当这个自由变量发生变化时,Scala的闭包能够捕获到这个变化,因此Scala的闭包捕获的是变量本身而不是当时变量的值。

比如:

scala> more =  9999
more: Int = 9999 scala> addMore ( 10)
res2: Int = 10009

同样的,如果变量在闭包在发生变化,也会反映到函数外面定义的闭包的值。比如:

scala> val someNumbers = List ( -11, -10, -5, 0, 5, 10)
someNumbers: List[Int] = List(-11, -10, -5, 0, 5, 10) scala> var sum =0
sum: Int = 0 scala> someNumbers.foreach ( sum += _) scala> sum
res4: Int = -11

可以看到在闭包中修改sum的值,其结果还是传递到闭包的外面。

如果一个闭包所访问的变量有几个不同的版本,比如一个闭包使用了一个函数的局部变量(参数),然后这个函数调用很多次,那么所定义的闭包应该使用所引用的局部变量的哪个版本呢? 简单的说,该闭包定义所引用的变量为定义该闭包时变量的值,也就是定义闭包时相当于保存了当时程序状态的一个快照。比如我们定义下面一个函数闭包:

scala> def makeIncreaser(more:Int) = (x:Int) => x + more
makeIncreaser: (more: Int)Int => Int scala> val inc1=makeIncreaser(1)
inc1: Int => Int = <function1> scala> val inc9999=makeIncreaser(9999)
inc9999: Int => Int = <function1> scala> inc1(10)
res5: Int = 11 scala> inc9999(10)
res6: Int = 10009

当你调用makeIncreaser(1)时,你创建了一个闭包,该闭包定义时more的值为1, 而调用makeIncreaser(9999)所创建的闭包的more的值为9999。此后你也无法修改已经返回的闭包的more的值。因此inc1始终为加一,而inc9999始终为加9999.

Scala闭包的更多相关文章

  1. Scala 闭包

    Scala 闭包 闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量. 闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数. 如下面这段匿名的函数: val multipl ...

  2. python 本地变量和全局变量 locals() globals() global nonlocal 闭包 以及和 scala 闭包的区别

    最近看 scala ,看到了它的作用域,特此回顾一下python的变量作用域问题. A = 10 B = 100 print A #10 print globals() #{'A': 10, 'B': ...

  3. scala 闭包的概念

    闭包本质上是一个函数和其引用的变量的统一定义,它的返回值依赖于这个函数外部的一个或者多个变量. var test = (i:Int) => i+sum 这里 i是一个形参, 随着函数的调用传入不 ...

  4. Spark记录-Scala函数与闭包

    函数声明 Scala函数声明具有以下形式 - def functionName ([list of parameters]) : [return type] Scala 如果不使用等号和方法体,则隐式 ...

  5. scala中的闭包

    scala闭包 代码示例: package test.close_pack import scala.collection.mutable.ArrayBuffer /** * AUTHOR Guozy ...

  6. Scala函数式编程进阶

    package com.dtspark.scala.basics /** * 函数式编程进阶: * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量: * 2, 函数更长用的方式 ...

  7. Scala入门之函数进阶

    /** * 函数式编程进阶: * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量: * 2, 函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要 ...

  8. 大数据系列修炼-Scala课程06

    关于Scala中的正则表达式与模式匹配结合的正则表达式Reg 正则表达式的实现:正则表达式的定义与其它语言差不多,只需在表达式后加一个.r,并且可以遍历相应的表达式进行匹配 //定义的正则表达式 va ...

  9. 一文学会Scala

    整体介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. 联邦理工学院洛桑(EPFL)的Martin Odersky于2001 ...

随机推荐

  1. 用 C# 读取二进制文件

    当想到所有文件都转换为 XML时,确实是一件好事.但是,这并非事实.仍旧还有大量的文件格式不是XML,甚至也不是ASCII.二进制文件仍然在网络中传播,储存在磁盘上,在应用程序之间传递.相比之下,在处 ...

  2. HelloXV1.77网络功能简介

    HelloXV1.77的网络功能做了较大程度的加强,移植了业界广泛使用的lwIP协议栈,并做了很多优化工作,修正了其中的一些bug.同时,实现了一个network字符界面应用程序,可以对网络功能进行调 ...

  3. apache开源项目--JMeter

    JMeter是Apache组织的开放源代码项目,它是功能和性能测试的工具,100%的用java实现.

  4. (转载)腾讯CMEM的PHP扩展

    (转载)http://blog.renren.com/share/223341289/7693783476 题外话 最近公司在做相关的业务,由于Memcached协议缺少返回码,为了保证业务数据的安全 ...

  5. Codeforces 302D

    思路:最短路,map[i][j] = d*(|x[i]-x[j]| + |y[i]-y[j]|) - add[i] #include<iostream> #include<cstdi ...

  6. zookeeper环境的搭建

    接管条件:磁盘上原数据完全一样,而自动接管,则是由zookeeper 实现的 FailloverController:控制namenode状态:检查namenode:通过远程协议

  7. 【CSS】Beginner3:Color

    1.red rgb(255,0,0) rgb(100%,0%,0%) #ff0000 #f00 2.Predefined color name aqua, black, blue, fuchsia, ...

  8. HDU 1907

    博弈入门题吧. 把尼姆博弈推广到n堆,都是用异或运算.还有个总结的地方是,只要先手面对的是奇异局势,则胜负都掌握在后手.本题,题目要求是最后拿完的输,尼姆博弈是最后拿完的赢.但实际上优先权都掌握在后手 ...

  9. 关于Spring的Controller及Struts的Action的多线程的注意

    struts是线程安全,并不是指多线程,而是指单态,当多个用户访问一个请求的时候,服务器内存中只有一个与之对应的action类对象,execute方法加上了同步关键字,如果你在action里加上一个全 ...

  10. POJ2689 - Prime Distance(素数筛选)

    题目大意 给定两个数L和U,要求你求出在区间[L, U] 内所有素数中,相邻两个素数差值最小的两个素数C1和C2以及相邻两个素数差值最大的两个素数D1和D2,并且L-U<1,000,000 题解 ...