Block

Blocks就是存放一些可以被执行的代码的块,通常用do...end 或者 {}表示

例如:

[1, 2, 3].each do |num|
puts num
end [1, 2, 3].each { |num| puts num }

Blocks可以和.each、.times等联合使用,用来对每一个元素执行一段指令。

还有很多非常有用的方法需要用到Blocks,例如 collect

collect方法可把数组中的每个元素都传给Blocks, 在Blocks中可对数组元素进行操作

例如:

my_nums = [1, 2, 3]
my_nums.collect! { |num| num ** 2 }

下面我们来想一下,为什么有些方法允许使用Blocks而有些不是

因为允许使用Blocks的methods有办法从调用方法把控制权转移到Blocks然后再转移回来到调用方法处。我们可以通过yield关键字来实现。

def block_test
puts "We're in the method!"
puts "Yielding to the block..."
yield
puts "We're back in the method!"
end block_test { puts ">>> We're in the block!" }
--------------------------------------------------------------------
输出运行结果:
We're in the method!
Yielding to the block...
>>> We're in the block!
We're back in the method!
nil

从上段程序可以看出, 当我们调用block_test时, 先进入block_test程序,然后运行, 当程序走到了yield处, 程序的控制权同过yield转移到了block中(即块

{puts ">>> We're in the block!"}), block执行完毕后, 再把程序控制权还给block_test方法, 程序从yield关键字后继续运行。

我们还可以给yield传参数

 def yield_name(name)
puts "In the method! Let's yield."
yield("Kim")
puts "In between the yields!"
yield(name)
puts "Block complete! Back in the method."
end yield_name("Eric") { |n| puts "My name is #{n}." } # Now call the method with your name!
yield_name("Wei") { |n| puts "My name is #{n}"}
-----------------------------------------------------------------
输出:
In the method! Let's yield.
My name is Kim.
In between the yields!
My name is Eric.
Block complete! Back in the method.
In the method! Let's yield.
My name is Kim
In between the yields!
My name is Wei
Block complete! Back in the method.
nil

分析此段代码:

1.我们定义了带有一个参数name的yield_name方法

2.在程序第9行,我们调用了yield_name方法并传入了参数"Eric", 因为yield_name包含yield语句,所以我们要提供一个block块

3.在yield_name中,我们传给了yield一个参数"Kim", 在block块中n现在存放的就是"Kim", 所以我们输出的是"My name is kim"

4.程序回到yield_name中, 下面有把yield_name的参数name(name中存放的是"Eric")传给了yield,所以我们输出"My name is Eric"

Proc

我们说过, 在Ruby中所用的一切都是对象, 这其实并非事实, 因为blocks不是对象。因此blocks不能被保存到变量, 并且不具备变量所拥有的任何能力。因此我们需要proc。

你可以认为一个proc存储一个block。 就像你可以把一段代码放在一个方法中一样, 你也可以把一个有名字的block放进proc中。proc是保证你代码的DRY(don't repeat yourself)的非常好的方式。如果使用block你必须在每次你要用到它的地方重新写一遍, 但是使用proc你的代码只要写一次就可以多次使用它。

proc的定义非常简单。 你仅仅需要调用Proc.new(Proc首字母大写), 然后传入一个你想要保存的block就可以了

例如:

floats = [1.2, 3.45, 0.91, 7.727, 11.42, 482.911]
round_down = Proc.new { |n| n = n.floor }
ints = floats.collect(&round_down)

我们可以传递proc给一个需要block的方法,我们不必一遍遍重写这个block。&用来把proc转换为block(因为.collect!和.map!通常需要使用block).

使用proc的好处:

1.proc是成熟的对象, 因此它具有一般对象所拥有的一切能力,而block不是对象。

2.不同于block,proc能被一次次使用而不用需要重写。

group_1 = [4.1, 5.5, 3.2, 3.3, 6.1, 3.9, 4.7]
group_2 = [7.0, 3.8, 6.2, 6.1, 4.4, 4.9, 3.0]
group_3 = [5.5, 5.1, 3.9, 4.3, 4.9, 3.2, 3.2] over_4_feet = Proc.new {|x| x >= 4} can_ride_1 = group_1.select(&over_4_feet)
can_ride_2 = group_2.select(&over_4_feet)
can_ride_3 = group_3.select(&over_4_feet)

我们还可以直接使用.call来调用proc

例如:

hi = Proc.new{ puts "Hello!" }
hi.call
------------------------------------------
输出
Hello!

当symbol遇到proc

我们同样也能用&把symbol转换为proc

strings = ["", "", ""]
nums = strings.map(&:to_i)
# ==> [1, 2, 3]

lambda

和proc一样,lambda也是对象。 除了一些语法上的差异和一些行为上的特性, lambda和proc是一样的。

写法: lambda {puts "Hello"} 和 Proc.new {puts "Hello"}

lambda的语法: lambda{ |para| block }

lambda在proc可以使用的地方一样有用。

strings = ["leonardo", "donatello", "raphael", "michaelangelo"]
symbolize = lambda { |para| para.to_sym }
symbols = strings.collect(&symbolize)
--------------------------------------------------------------------
输出 [:leonardo, :donatello, :raphael, :michaelangelo]

上面代码中 lambda 有一个参数, 并且对这个参数使用.sym方法把字符串转换为symbol。 &用来把lambda转换成block。

lambda vs proc

如果你感觉proc和lambda非常相似, 这是因为他们确实非常相似。。。

它们只有两个主要区别:

1.lamba检查传进来参数的数量,而proc不用。这意味着当你传进错误数量的参数时lambda将会抛出错误,而proc将会忽略不被期望使用的参数,并把它们赋值为nil。

2.当lambda返回时, 它把控制权转移给方法, 而当proc返回时, 它直接返回而不回到调用方法。

例如:

def batman_ironman_proc
victor = Proc.new { return "Batman will win!" }
victor.call
"Iron Man will win!"
end puts batman_ironman_proc
--------------------------------------------------------------
输出
Batman will win!
nil
def batman_ironman_lambda
victor = lambda { return "Batman will win!" }
victor.call
"Iron Man will win!"
end puts batman_ironman_lambda
----------------------------------------------------------
输出:
Batman will win!
Iron Man will win!
nil

Ruby中Block, Proc, 和Lambda的更多相关文章

  1. ruby中Block, Proc 和 Lambda 浅析

    Block 与Proc的区别: Block是代码块,Proc是对象: 参数列表中最多只能有一个Block, 但是可以有多个Proc或Lambda; Block可以看成是Proc的一个类实例. Proc ...

  2. ruby中的可调用对象--proc和lamdba

    ruby中将块转变成对象的三种方法 ruby中的大部分东西都是对象,但是块不是.那么,如果你想存下来一个块,方便以后使用,你就需要一个对象.ruby中有三种方法,把块转换成可以利用的对象. Proc. ...

  3. Ruby中的语句中断和返回

    李哲 - APRIL 28, 2015 return,break,next 这几个关键字的使用都涉及到跳出作用域的问题,而他们的不同 则在于不同的关键字跳出去的目的作用域的不同,因为有代码块则导致有一 ...

  4. ruby中proc和lambda的return区别

    学习ruby有一段时间了,但是我看了好几遍proc和lambda的return区别的区别讲解,始终没明白到底什么区别,今天上午又看,终于感觉是茅塞顿开有点领悟了 一下内容部分来自<<rub ...

  5. [翻译]理解Ruby中的blocks,Procs和lambda

    原文出处:Understanding Ruby Blocks, Procs and Lambdas blocks,Procs和lambda(在编程领域被称为闭包)是Ruby中很强大的特性,也是最容易引 ...

  6. Ruby Proc 和 lambda的共同点和区别

    Proc 和 lambda 的目的是把block {....} 变成类似方法一样的对象,使其不需要重复编写同样的block. Proc 和 lambda 的共同点: 语法类似Proc.new{|n| ...

  7. 理解Ruby中的作用域

    作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够, ...

  8. ruby中的可调用对象--方法

    上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...

  9. Ruby 中的闭包-代码块

    看了一片文章https://ruby-china.org/topics/38385讲closure的. 写下一些感想: 闭包就是 一个函数能够记住和存取它的lexical作用域,即使这个函数是在它的l ...

随机推荐

  1. Timer

    timer类有三种 1.System.Windows.Forms.Timer  使用地方:Windows 窗体应用程序中,并且必须在窗口中使用.  2.System.Timers.Timer 使用地方 ...

  2. Jquery 随便写些知识点

    针对jQuery随便写些觉得还挺实用的一些东西,也没系统的去理一番,只是想到哪写到哪,写的不完全也请多见谅. jQuery和其他javascript库产生$符号冲突了?$符号想必用jQuery的人都不 ...

  3. WPF控件ComboBox 每个Item的ToolTip引发的异常

    介绍 首先介绍下要实现的任务.做一个下拉框,当选择每个项的时候将鼠标发在上面显示该项的ToolTip的内容(Image). 实现 Model: public class SkinInfo : Noti ...

  4. Alpha版本十天冲刺——Day 2

    站立式会议 会议总结 队员 今天完成 遇到的问题 明天要做 感想 鲍亮 学习post请求连接服务器,学习git 无 http资源请求方法封装,完成Android验证码获取接口和登录验证接口 今天满课, ...

  5. 北京地铁站点遍历最少经站次数问题普遍意义上是一个NP问题,目前不存在多项式时间算法能够解决该问题

    http://www.cnblogs.com/jiel/p/5852591.html 众所周知求一个图的哈密顿回路是一个NPC问题: In the mathematical field of grap ...

  6. Objective -C学习笔记 之copy(复制)

    //自定义类对象实现copy需要遵守copy协议(否则程序崩溃),实现必须实现的协议方法,里面的代码就决定了你的copy是深是浅 #import <Foundation/Foundation.h ...

  7. 获取字符串中每个字符出现的次数(利用TreeMap)

    案例:"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)分析1:定义一个字符串(可以改进为键盘录入)2:定义一个 ...

  8. aircrack-ng 多网卡启动后环境清理

    #!/bin/sh pkill airodump airmon-ng stop wlan0mon service network-manager restart rm -rf sadsad*

  9. 从零开始HTML(一 2016/10/17)

    就是准备跟着霹雳猿教程过一遍HTML啦,边看边记录更便于理解记忆吧~ 1.属性 HTML 标签可以拥有属性.属性提供了有关 HTML 元素的更多的信息.属性总是以名称/值对的形式出现,比如:name= ...

  10. 仿照jquery封装一个自己的js库(一)

    所谓造轮子的好处就是复习知识点,加深对原版jquery的理解. 本文系笔者学习jquery的笔记,记述一个名为"dQuery"的初级版和缩水版jquery库的实现.主要涉及知识点包 ...