码迷,mamicode.com
首页 > 其他好文 > 详细

Ruby 中的闭包-代码块

时间:2019-08-31 13:02:10      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:lambda   ruby   概念   简单   创建   本质   存在   add   isp   

看了一片文章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 中的闭包-代码块

标签:lambda   ruby   概念   简单   创建   本质   存在   add   isp   

原文地址:https://www.cnblogs.com/chentianwei/p/11438465.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!