Ruby代码块(Block)
1、什么是代码块
在Ruby中,{}或do...end之间的代码是一个代码块。代码块只能出现在一个方法的后边,它紧接在方法最后一个参数的同一行上,由yield关键字调用。例如:
[1,2,3,4,5].each { |i| puts i }
[1,2,3,4,5].each do |i|
puts i
end
块变量:以yield关键字调用block也可以传递参数,block中竖线(|)之间给出的参数名用于接收来自yield的参数。
竖线之间(如上例中的 | i |)的变量被称作块变量,作用和一个正常方法的参数一样
2、{}和do...end优先级不同
在传递一个block时,使用{}传递的block比使用do…end的优先级要高;
为了避免引起歧义,最好使用()将参数括起来。例如:
1.upto 3 do |x|
puts x
end
是正确的,但是 1.upto 3 {|x| puts x} 编译不通过,应该写成 1.upto(3) {|x| puts x}
原因:
1.upto 3 do…end 中block会传递到upto方法里面,3会作为一个参数传递给upto
1.upto 3 {|x| puts x} 一句会把3当做函数名,将block传递到这个函数,其返回值作为upto方法的参数,所以编译不过,需加()。
3、代码块转化为对象的方法
代码块并不是对象,但可以通过以下三种方法转化为Proc类的对象:
(1)将一个代码块传递给最后一个参数以 & 开始的方法。例:
def meth1(p1, p2, &block)
puts block.inspect
puts block.call
end
meth1(1, 2) { "This is a block" }
(2)使用Proc.new方法,代码块作为参数:
block = Proc.new { "a block" }
(3)调用Kernel.lambda方法:
block = lambda { "a block" }
前两种方法是等价的,会检查参数的数量,但Proc.new 创建的对象不会;
用 lambda 和 Proc.new 生成的 Proc 对象之间也是有差别的。这个差别与 return 关键字相关。lambda 中的 return 从 lambda 返回。而 Proc.new 中的 return 从外围方法返回。
# 执行后"Never come here"不会被输出,执行p.call相当于在test_proc方法内执行了return语句。
def test_proc
p = Proc.new { return 1 } # test_proc方法返回
p.call
puts "Never come here" # 永远不会执行到
end # 使用lambda生成的Proc对象执行call方法调用时,return表示从lambda包围得块内返回。
def test_lambda
p = lambda { return 1 }
result = p.call
puts "The value is: #{result}"
end
Note:在一个代码块中执行next语句会导致代码块返回。返回值就是next语句后带的参数。如果next后没有参数,那么返回值为nil。
def meth2
result = yield
p "The block result is #{result}"
end puts meth2 { next 9 }
pr = Proc.new { next 100 }
puts pr.call
pr = lambda { next }
puts pr.call 执行结果为:
The block result is 9
100
nil
4、yield关键字调用代码块
在方法中可以使用 yield 来执行代码块的内容,就好像传入的代码块是这个方法的一部分一样。每当碰到一个 yield,代码块的内容就会被执行一次,代码块执行结束后,程序会回到 yield 的那一行继续向下执行。
使用 yield 可以向代码块传递参数,也可以从代码块取回返回值,返回值就是代码块中最后一个表达式的值。
def fibonacii(max)
f1, f2 = 1, 1
while f1 <= max
yield f1
f1, f2 = f2, f1+f2
end
end fibonacii(1000) { |f| print f, " " } 执行结果为:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
(1)在这个例子中,yield 接收一个参数f1,这个参数将会在执行的时候传递给指定的代码块。在代码块中,接收的参数使用两个竖线括起来放在代码块的头部。
(2)另外,在使用 yield 关键字调用代码块时,如果传入的参数个数少于代码块中定义的参数个数,那么没有传递的参数会自动转为nil。反之,则最后一个参数为一个数组,该数组包含了剩余的传递参数;
Ruby代码块(Block)的更多相关文章
- 04OC之分类Category,协议Protocol,Copy,代码块block
一.Protocol协议 我们都知道,在C#有个规范称之为接口,就是规范一系列的行为,事物.在C#中是使用Interface关键字来声明一个接口的,但是在OC中interface是用来声明类,所以用了 ...
- [转]iOS代码块Block
代码块Block是苹果在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,Block是一种特殊的数据类型,其可以正常定义变量.作为参数.作为返回值,特殊地,Block还可以保存一段代码,在需要 ...
- iOS学习之代码块(Block)
代码块(Block) (1)主要作用:将一段代码保存起来,在需要的地方调用即可. (2)全局变量在代码块中的使用: 全局变量可以在代码块中使用,同时也可以被改变,代码片段如下: ;//注意:全局变量 ...
- 从C#到Objective-C,循序渐进学习苹果开发(4)--代码块(block)和错误异常处理的理解
本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验.本文继续上一篇随笔<从 ...
- Objective-C-----协议protocol,代码块block,分类category
概述 ObjC的语法主要基于smalltalk进行设计的,除了提供常规的面向对象特性外,还增加了很多其他特性,本文将重点介绍objective-C中一些常用的语法特性. 当然这些内容虽然和其他高级语言 ...
- 代码块(block)的使用
Objective-C语法之代码块(block)的使用 代码块本质上是和其他变量类似.不同的是,代码块存储的数据是一个函数体.使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值. 脱 ...
- 一篇文章看懂iOS代码块Block
block.png iOS代码块Block 概述 代码块Block是苹果在iOS4开始引入的对C语言的扩展,用来实现匿名函数的特性,Block是一种特殊的数据类型,其可以正常定义变量.作为参数.作为返 ...
- Objective-C 代码块(block)的使用
代码块本质上是和其他变量类似.不同的是,代码块存储的数据是一个函数体.使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值. 脱字符(^)是块的语法标记.按照我们熟悉的参数语法规约所定 ...
- Objective-C语法之代码块(block)的使用
代码块本质上是和其它变量相似.不同的是,代码块存储的数据是一个函数体.使用代码块是,你能够像调用其它标准函数一样,传入參数数,并得到返回值. 脱字符(^)是块的语法标记.依照我们熟悉的參数语法规约所定 ...
随机推荐
- 12.Django数据库操作(执行原生SQL)
1.使用extra方法 解释:结果集修改器,一种提供额外查询参数的机制 说明:依赖model模型 用在where后: Book.objects.filter(publisher_id="1& ...
- eclipse svn 分支合并到主干
最近公司产品上线,整个系统架构包含有七八个子系统,并且子系统都是集群部署.所以每次升级维护都要确保尽可能不出问题.因为整个系统刚上线不久,意味着新系统不定期有BUG需修复,但新功能模块也在持续的开发中 ...
- python-2 什么是函数
函数是什么? 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 形参变量只有在被调用时才 ...
- 第一章 python中重要的数据结构(上)
最近,由于工作需要,使用python开发公司的运维自动化平台,所以找本书来并结合官方手册,开始python的学习之旅. 一.列表 [含义]:列表用中括号表示,通过逗号进行分隔一组数据(可以为不同的数据 ...
- POJ 1611并查集
我发现以后写题要更细心,专心! #include<iostream>#include<algorithm>#include<stdio.h>#include< ...
- Spring Cloud之Zuul网关集群
Nginx+Zuul 一主一备 或者 轮训多个 在微服务中,所有服务请求都会统一到Zuul网关上. Nginx 配置: #user nobody; worker_processes 1; #error ...
- Linux Glibc库严重安全漏洞修复方案通知(腾讯开发者社区)
如何查看当前glibc的版本号? rpm -aq | grep glibc 尊敬的用户: 您好!2015年1月28日, 腾讯云安全情报监测到LinuxGlibc库存在一处严重安全漏洞,可以 ...
- electron—Chromium有酒,Node有肉
谷歌V8引擎的出现,Node.js的诞生注定要把开发模式“搅乱”. 基于云应用,服务化,定制化的应用需求不断增加后使得传统的winform开发空间越来越小,而原来做前端的空间越来越大,Node.js ...
- linux 各个文件系统之间的关系
linux 系统的各个文件系统是内置于内核中的,用vfs屏蔽了各个文件系统对于文件操作的差异,用户进程是通过系统调用来操作文件系统中的文件的.
- JavaScript 使用技巧(持续更新)
JavaScript 使用技巧(持续更新) 类型检测 使用Object.prototype.toString.call(obj)的方式. 因为无论typeof还是instanceof都无法做到精确判断 ...