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中的静态代码块、构造代码块、构造函数、局部代码块区别
构造代码块: 在类中定义可以给所有对象进行初始化.局部代码块: 在方法中定义属性的生命周期.静态代码块: 在类中定义用于给类调用时属性的初始化 构造函数与构造代码块的区别: 构造函数是给对应的对象进行 ...
随机推荐
- MariaDB知识点总结02--日志+备份
一.日志 1.查询日志 记录每一条sql语句,建议不开启,因为如果访问量较大,会占用相当大的资源,影响性能; vim /etc/my.cnf.d/server.cnf general_log = ON ...
- 配置nova-compute在不同的hypervisors上使用不同的存储后端
说明:主参考:https://www.sunmite.com/openstack/use-local-storage-for-different-hypervisors.html 在控制节点上执行 1 ...
- webdriver的八种定位
转自https://zhuanlan.zhihu.com/p/54588889 在UI层面的自动化测试开发中,元素的定位与操作是基础,也是经常遇到的困难所在.webdriver提供了8种定位: 1. ...
- APP安全测试要点
APP面临的威胁 APP评估思路 APP自动化检测思路 安全测试要点 证书和签名 将apk文件更名为zip 使用unzip解压 META-INF中包含签名文件和真正的CERT.RSA文件(公钥证书自签 ...
- Linux命令---ln、readlink
ln 无参数--------创建硬链接 -s -------------创建软链接 用法:ln [option] 源文件 目标文件 ln test.txt test_hard.txt 只有在同 ...
- python列表的切片与复制
切片,即处理一个完整列表中部分数据. 语法 变量[起始索引:终止索引:步长] 首先创建一个字符串列表 >>> cars = ['toyota', 'honda', 'mazda', ...
- vue60秒倒计时
wait:"60", content:"验证码", canClick: true, daojishi(){ if(!this.canClick) return ...
- sql server存储引擎启动错误(SQL Server could not spawn FRunCM thread)
错误信息: 中文版: 服务器无法在 'any' <ipv4> 1433 上侦听.错误: 0x277a.若要继续,请通知您的系统管理员. TDSSNIClient 初始化失败,出现错误 0x ...
- 【0.4】mysql版本特性(5.6-8.0)【转】
转自:http://blog.itpub.net/15498/viewspace-2650661/ MySQL 5.6 1).支持GTID复制 2).支持无损复制 3).支持延迟复制 4).支持基于库 ...
- django进阶版2
目录 批量插入数据 自定义分页器 创建多表关系的3种方法 全自动 全手动 半自动 form组件 如何渲染页面 第一种方式 第二种方式 第三种方式 如何显示错误信息 forms组件钩子函数 局部钩子 全 ...