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中的静态代码块、构造代码块、构造函数、局部代码块区别
构造代码块: 在类中定义可以给所有对象进行初始化.局部代码块: 在方法中定义属性的生命周期.静态代码块: 在类中定义用于给类调用时属性的初始化 构造函数与构造代码块的区别: 构造函数是给对应的对象进行 ...
随机推荐
- Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II)
Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II) 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n ...
- cisco上配置 pppoe拨号
r1(config)#vpdnenable 开启虚拟拨号VPDN r1(config)#vpdn-groupoffice 定义组 ...
- 李宏毅 Tensorflow解决Fizz Buzz问题
提出问题 一个网友的博客,记录他在一次面试时,碰到面试官要求他在白板上用TensorFlow写一个简单的网络实现异或(XOR)功能.这个本身并不难,单层感知器不能解决异或问题是学习神经网络中的一个常识 ...
- vue-cli按需引入Element UI组件
一.环境 使用vue-cli搭建的环境 二.安装 babel-plugin-component npm install babel-plugin-component -D 三.修改.babelrc文件 ...
- 使用sequelize-auto生成sequelize的Models
一.全局安装sequelize-auto npm install -g sequelize-auto 二.全局安装对应数据库的驱动,此处使用的是mysql npm install -g mysql 三 ...
- SQL --------JDBC 用用户名查询用户的信息
package demo; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; ...
- git 命令 查看历史提交 git log
怎么理解git commit 命令 git commit 相当于 我们虚拟机快照操作,每次执行commit命令 相当于对本地仓库做一次快照,保存了当时仓库的状态, git commit -m 加上的& ...
- 使用zookeeper作为分布式锁以及设计一种通知监听模式
1.创建实例/** * 初始化单例的便捷方法 */ public static void init() { getInstance(); } /** * 获取单例 * @return */ publi ...
- PYTHON 100days学习笔记008-1:数据结构补充
目录 Day008_01:数据结构补充 1.列表list 1.1 将列表当作堆栈使用 1.2 将列表当作队列使用 1.3 列表推导式 1.4 嵌套列表解析 1.5 del语句 2.元组和序列 3.集合 ...
- Linux下测试ZLAN 5800
今天师兄让帮忙测试ZLAN 5800八串口通信模块,windows下的测试按照手册来已经搞定,接下来是Linux下的测试. 因为厂家不提供Linux下的相关资料,所以需要在windows下设置好后直接 ...