Scala闭包
假如我们定义如下的函数:
(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闭包的更多相关文章
- Scala 闭包
Scala 闭包 闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量. 闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数. 如下面这段匿名的函数: val multipl ...
- python 本地变量和全局变量 locals() globals() global nonlocal 闭包 以及和 scala 闭包的区别
最近看 scala ,看到了它的作用域,特此回顾一下python的变量作用域问题. A = 10 B = 100 print A #10 print globals() #{'A': 10, 'B': ...
- scala 闭包的概念
闭包本质上是一个函数和其引用的变量的统一定义,它的返回值依赖于这个函数外部的一个或者多个变量. var test = (i:Int) => i+sum 这里 i是一个形参, 随着函数的调用传入不 ...
- Spark记录-Scala函数与闭包
函数声明 Scala函数声明具有以下形式 - def functionName ([list of parameters]) : [return type] Scala 如果不使用等号和方法体,则隐式 ...
- scala中的闭包
scala闭包 代码示例: package test.close_pack import scala.collection.mutable.ArrayBuffer /** * AUTHOR Guozy ...
- Scala函数式编程进阶
package com.dtspark.scala.basics /** * 函数式编程进阶: * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量: * 2, 函数更长用的方式 ...
- Scala入门之函数进阶
/** * 函数式编程进阶: * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量: * 2, 函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要 ...
- 大数据系列修炼-Scala课程06
关于Scala中的正则表达式与模式匹配结合的正则表达式Reg 正则表达式的实现:正则表达式的定义与其它语言差不多,只需在表达式后加一个.r,并且可以遍历相应的表达式进行匹配 //定义的正则表达式 va ...
- 一文学会Scala
整体介绍 Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性. 联邦理工学院洛桑(EPFL)的Martin Odersky于2001 ...
随机推荐
- 结构体dict_table_t
typedef struct dict_table_struct dict_table_t; /** Data structure for a database table. Most fields ...
- 把USB打印机映射到LPT端口
把USB打印机映射到LPT端口(pos小票机测试成功)2010-12-23 18:11:00| 分类: 編程 | 标签: |字号大中小 订阅 注释:在DOS命令行下运行以下命令(以下为示例,根据实际情 ...
- EventHandlerList z
写一个类时,有时候会在同一个类上添加很多事件,事件很多的话,是不容易管理的,.NET提供的EventHandlerList可以辅助多个事件的管 理,但不方便的地方是,它不是类型安全的,缺少类型安全,多 ...
- C# 多线程是否结束可通过线程池可以判断
C# ManualResetEvent信号状态判断线程池是否结束 这是一段重要的代码,小猪两个小时的研究成果,记下来备查. using System; using System.Collection ...
- HADOOP2.2.0安装配置指南
一. 集群环境搭建 这里我们搭建一个由三台机器组成的集群: Ip地址 用户名/密码 主机名 集群中角色 操作系统版本 192.168.0.1 hadoop/hadoop Hadoop-mast ...
- lua使用优化建议
1.使用局部变量local 这是最基础也是最有用的策略,虽然使用全局变量并不能完全避免,但还是应该尽量避免,取而代之使用局部变量即local.这里的局部变量也包括函数function,因为在Lua里函 ...
- HW2.7
import java.util.Scanner; public class Solution { public static void main(String[] args) { Scanner i ...
- Trie树模板~~~
* + ; ; // 字母表为全体小写字母的Trie struct Trie { int ch[maxnode][sigma_size]; int val[maxnode]; int sz; // 结 ...
- NULL指针 Void* 和野指针
在C和C++的语言中常常有这几个概念: NULL指针.空指针.Void *指针.野指针(Wild Pointer)甚至垂悬指针(Dangling Pointer). 1.NULL指针,一般用于指向一个 ...
- 函数(C++ Primer读书笔记)
C++ Primer 第五版课后题 练习6.32 :下面的函数合法吗?如果合法,说明其功能:如果不合法,修改其中的错误并解释原因. #include <iostream> using na ...