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中的静态代码块、构造代码块、构造函数、局部代码块区别
构造代码块: 在类中定义可以给所有对象进行初始化.局部代码块: 在方法中定义属性的生命周期.静态代码块: 在类中定义用于给类调用时属性的初始化 构造函数与构造代码块的区别: 构造函数是给对应的对象进行 ...
随机推荐
- 【AMAD】django-countries -- 为Django app的form提供country选项,为model提供CountryField
动机 简介 个人评分 动机 有时候看一些数据库设计,国家数据会存在一个单独的表里面.这种方式读取数据库无疑又要加上一层join,很不划算. 简介 [django-countries]1解决的是: 不用 ...
- js单击事件
<script type="text/javascript"> // 根据ID获取元素,得到按钮[注册] var elbtn=document.getElementBy ...
- python pip换源方法
以下资料来源于网络: pip国内的一些镜像 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ust ...
- Design Snake Game
Design a Snake game that is played on a device with screen size = width x height. Play the game onli ...
- hashmap 为什么初始化容量是2的幂次方
个人理解 做下记录,不正确的地方望不吝赐教 这是hashmap初始化容量时候 对容量大小做的处理,保证初始化容量为最近的2的幂次方(JDK1.8) static final int tableSize ...
- Nginx的一些常用配置
#定义Nginx运行的用户和用户组 #user nobody; #nginx进程数,建议设置为等于CPU总核心数. worker_processes 1; #全局错误日志定义类型,[ debug | ...
- 洛谷 P1266 速度限制 题解
题面 这道题可以理解为是一个分层图,也可以理解为是二维的SPFA dis[i][j]表示到达i这个点速度为j的最短路 然后跑已经死了的SPFA就好了: #include <bits/stdc++ ...
- 后缀数组 LCP--模板题
题意: 给你S串和T串,用T串的所有前缀去匹配S串(匹配值是最长公共子串). 问你总值相加是多少. 思路: 先把两个S,T串倒过来,再拼接 S#T 合成一串,跑一下后缀数组 在排序好的rank里计算每 ...
- phpexcel 生成大于26列数据
function excelExport2($fileName = '', $headArr = [], $data = [], $widths=[]) { ob_clean(); // $fileN ...
- Spring MVC(一)Spring MVC的原理
1.Spring MVC的目的 构建像Spring框架那样灵活和松耦合的Web应用程序. 2.Spring MVC中如何处理Request? 每当用户在Web浏览器中点击链接或者提交表单时,Reque ...