Ruby 中的闭包-代码块
看了一片文章https://ruby-china.org/topics/38385讲closure的。
写下一些感想:
闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的lexical作用域的外面执行。
当一个函数被写出来时,这个函数的closure就已经确定了。
javascript中有闭包的概念:https://www.cnblogs.com/chentianwei/p/9739714.html
Ruby中的关键字定义def是没有闭包的。它创建一个封闭的作用域。
但是Ruby有闭包的概念这就是--代码块。
a = 100 define_method :add_a do
a = a + 1
end puts add_a # => 101
puts add_a # => 102
puts add_a # => 103
这个例子使用了define_method方法搭配一个代码块来定义方法。我们就可以访问外部的作用域的局部变量a。
Ruby就是使用代码块来表示闭包的。
可以参考《Ruby元编程》相关章节的例子:
def my_method
x = "GoodBye"
puts yield("cruel")
end x = "Hello"
my_method do |y|
"#{x}, #{y} world!"
end
代码块绑定了变量x。即外部作用域的变量跟着代码块一起走!
代码块的意义:
在Ruby的开源世界,代码块无处不在:
1.容错涉及:
Ruby承袭于Lisp,代码块的运行会自动返回最后一条语句或者表达式的值,于是有些库也考虑到了用代码块来进行容错处理。
例子:
> hash = {}
> value = hash.fetch('a') { 'default value' }
=> "default value"
因为hash是空的,没有"a", 所以会返回代码块中的字符串,如果不提供代码块,就会报错❌。
2. DSL
3. 蹩脚的函数
代码块可以看作是一个蹩脚的函数,虽然一般情况下可以作为某个方法的回调,但在Ruby中代码块需要依赖其他机制来存在,而不是JS中的函数那样独立存在。
当使用代码块来定义一个匿名函数时,需要搭配lambda关键字或Proc类来实现。
> c = lambda() {}
=> #<Proc:0x00007ff47b8546a8@(irb):6 (lambda)>
> c.class
=> Proc
> (lambda() { 'hello' }).call
=> "hello"
> (lambda() { 'hello' })[]
=> "hello"
> (Proc.new { 'hello' }).call
=> "hello"
> (Proc.new { 'hello' })[]
=> "hello"
x = "tom"
(lambda() {"Hello,#{x}"}).call
以上都是常用的定义匿名函数的方式,本质上它们都是Proc类的实例,需要显式地利用Proc#call方法或者语法糖[]来调用它们。
总结:
这篇文章介绍了Ruby中的闭包概念, 它和封闭作用域的方法(使用def关键字定义的方法)有什么不同。
⚠️ Ruby中定义了三个地方为封闭的作用领域(对应三个关键字):
- 类定义 class
- 模块定义 module
- 方法def
区别于一般的方法,闭包在Ruby中以代码块的形式出现,它在Ruby世界中几乎无处不在,充当了一等公民。这种区分,不仅使我们的Ruby代码更加优雅,增添了可读性,还使得我们的编码过程更加简单。
Ruby 中的闭包-代码块的更多相关文章
- 2.java中c#中statc 静态调用不同之处、c#的静态构造函数和java中的构造代码块、静态代码块
1.java和c#静态成员调用的不同之处 static 表示静态的,也就是共享资源,它是在类加载的时候就创建了 java中 可以通过实例来调用,也可以通过类名.成员名来调用,但是一般最好使用类名. ...
- Java中的构造代码块
代码块 ----a静态代码块 ----b构造代码块 ----c普通代码块 执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. a.静态代码块: 静态代码块 ...
- Gradle中的buildScript代码块
在编写Gradle脚本的时候,在build.gradle文件中经常看到这样的代码: build.gradle 1 2 3 4 5 6 7 8 9 buildScript { repositories ...
- java中静态的代码块,静态变量,静态方法
简单了解一下java虚拟机--jvm几个内存区域: 方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息.常量.静态变量以及方法代码的内存区域, 常量池:常量池是方法区的一部分,主要用来存放 ...
- Java中的局部代码块、构造代码块、静态代码块
局部代码块: 作用:控制变量的生命周期: 在程序中,当我们已经使用完 x 后,并且在接下来的代码中,不会再用到x,那么就没必要让x 在内存中占用空间了,这用情况下,可以使用 局部代码块,将x及其所设计 ...
- [转] Gradle中的buildScript代码块
PS: 在build script中的task apply plugin: 'spring-boot' 需要 classpath("org.springframework.boot:spri ...
- java中的静态代码块等执行顺序
http://www.cnblogs.com/naruto469/p/3608459.html public class Print { 2 3 public Print(String s){ 4 S ...
- java中的static代码块为什么只执行一次
原因在最后,这是其中的一个小例子. 如: SessionFactory负责保存和使用所有配置信息,消耗内存资源非常大 所以一个web项目要保证只创建一个SessionFactory 那么在使用hibe ...
- 5.1JAVA基础复习——JAVA中的静态代码块、构造代码块、构造函数、局部代码块区别
构造代码块: 在类中定义可以给所有对象进行初始化.局部代码块: 在方法中定义属性的生命周期.静态代码块: 在类中定义用于给类调用时属性的初始化 构造函数与构造代码块的区别: 构造函数是给对应的对象进行 ...
随机推荐
- python界面编程
这是一个简单的加法计算器 首先,要先对这个简易计算器进行布局设计,需要两个输入框,还有一个输入框用于存放就算的结果,还需要两个table,一个是"+"一个是"=" ...
- python数值列表
使用range函数生成数值列表 使用range函数打印1~5的数字 for i in range(1,6): print(i) 输出 1 2 3 4 5 利用range函数生成数值列表 >> ...
- java中的 |=、&=、^=
|= 关于 |= 运算符:|= 运算符和 += 这一类的运算符一样,拆解开就是 a = a | b: 代码如下: public static strictfp void main(String[] ...
- Python三大主流框架的对比
相信做Python这一块的程序员都有听说这三个框架,就像神一样的存在,每一个框架的介绍我就不写出来了,感兴趣可以自己百度了解了解!下面我就说正事 Django:Python 界最全能的 web 开发框 ...
- 简单Kibana命令
1 查看健康状态 GET _cat/health?v epoch timestamp cluster status node.total node.data shards 1531290005 14: ...
- QByteArray详解
QByteArray在串口通讯中经常被使用,有一定必要较为全面详细的对QByteArray进行阐述.本文通过以下几个部分加以介绍: 1. 初始化 2. 访问与赋值 3. 添加.删除.插入与替换操作 4 ...
- CentOS/RHEL 安装EPEL第三方软件源
EPEL源简介 EPEL(Extra Packages for Enterprise Linux) 是由 FedORA 社区打造,为 RHEL 及衍生发行版如 CentOS等提供高质量软件包的项目.装 ...
- Spring中常用的设计模式之:代理模式
看了tom老师讲的深入分析spring源码,讲的挺好,做个小总结 代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以 ...
- [Android] Installation failed due to: ''pm install-create -r -t -S 4590498' returns error 'UNSUPPORTED''
小米特有问题 关闭开发者选项的启用MIUI优化 不得不说, 这是真的坑...
- js之数据类型(对象类型——构造器对象——对象)
JavaScript中除了原始类型,null,undefined之外就是对象了,对象是属性的集合,每个属性都是由键值对(值可以是原始值,比如说是数字,字符串,也可以是对象)构成的.对象又可分为构造器对 ...