ruby 疑难点之—— yield 和 yield self
yield
所有的"方法(methods)"隐式跟上一个"块(block)"参数。
块参数也可以明确给定,形式就是在参数前面加一个"&",比如 def fn(arg1, arg2, &block) end,其中的 &block 就是明确给定的块参数。
块参数的动作,可以通过调用 call() 方法执行,还可以用 yield 来执行 —— yield 其实就是一个语法糖。
所以以下几种写法常常是等价的:
- #method receives an invisible block argument
- def foo1()
- yield 1
- end
- #specify it explicitly
- def foo2(&block)
- yield 1
- end
- #yield is equal to block.call
- def foo3(&block)
- block.call(1)
- end
- #function call
- foo1 {|x| puts x} # =>
- foo2 {|x| puts x} # =>
- foo3 {|x| puts x} # =>
Proc
前面说到所有方法都可以隐式或显式指定一个块参数,那么块参数到底是什么呢?
答案是 Proc 对象,一个具有 call 方法的对象。
Proc 对象的定义有几种形式:
- 直接使用 {}
- 使用 Proc.new {}
- 使用 proc {}
- 使用 lambda {}
- #yield is equal to block.call
- def foo(&block)
- puts block.class
- puts block.to_s
- yield 1
- end
- #function call
- # Proc created using {} syntax
- foo {|x| puts x}
- # => Proc
- # => #<Proc:0x00000000e0b140@(ruby):9>
- # =>
- # Proc created with the "proc" keyword. Note & syntax when calling.
- my_proc = proc { |n| puts n }
- foo(&my_proc)
- # => Proc
- # => #<Proc:0x00000000e0b140@(ruby):12>
- # =>
- # Proc creates with Proc.new
- my_proc = Proc.new { |n| puts n }
- foo(&my_proc) # => 1
- # => Proc
- # => #<Proc:0x00000000e0b140@(ruby):16>
- # =>
- # Proc created with the "lambda" keyword. Nearly same thing.
- my_proc = lambda { |n| puts n }
- foo(&my_proc)
- # => Proc
- # => #<Proc:0x00000000e0b140@(ruby):20 (lambda)>
- # =>
yield self
在一个对象中,self 表示是一个当前对象的引用。
所以,常见的 yield self if block_given? 中的 self 就和其它地方使用 self 一样,没什么特殊的。
- class C1
- def foo(&block)
- puts block.class
- puts block.to_s
- yield self if block_given?
- yield "AAAAAAAAA"
- end
- end
- class C2
- def foo(&block)
- puts block.class
- puts block.to_s
- yield self if block_given?
- yield "BBBBBBBBB"
- end
- def to_s
- "XXXXXXXXXX"
- end
- end
- c1 = C1.new
- c1.foo {|x| puts x}
- # => Proc
- # => #<Proc:0x00000001c84aa0@(ruby):23>
- # => #<Context::C1:0x00000001c84af0>
- # => AAAAAAAAA
- c2 = C2.new
- c2.foo {|x| puts x}
- # => Proc
- # => #<Proc:0x00000001c842f8@(ruby):26>
- # => XXXXXXXXXX
- # => BBBBBBBBB
注意事项
method 定义中 &block 参数必须在最后
- # 正确示例
- def foo(arg1, arg2, &block)
- puts block
- end
- #function call
- block = proc {|x| puts x}
- foo( 1, 2, &block)
- # => #<Proc:0x000000011f3aa0@(ruby):14>
- #错误示例
- def foo(arg1, &block, arg2) # => (ruby): syntax error
- puts block
- end
yield 相当于是 block.call() 方法的调用,所以参数个数也需要对应
- def foo()
- yield 1,2,3 # 这里的 1 2 3 就是传递的参数
- end
- #function call
- foo {|x| puts x} # => 1
- foo {|x,y,z| puts z} # => 3
- foo {|x,y,z,k| puts k} # 为空
ruby 疑难点之—— yield 和 yield self的更多相关文章
- python yield 与 yield from转
python yield 与 yield from转 https://blog.csdn.net/chenbin520/article/details/78111399?locationNum=7&a ...
- yield与yield from
yield 通过yield返回的是一个生成器,yield既可以产出值又可以生成值,yield可以用next()来启动生成器,同时可以用send向生成器传递值:在初次启动生成器时,需调用next()或s ...
- 从yield 到yield from再到python协程
yield 关键字 def fib(): a, b = 0, 1 while 1: yield b a, b = b, a+b yield 是在:PEP 255 -- Simple Generator ...
- 60、简述 yield和yield from关键字。
1.可迭代对象与迭代器的区别 可迭代对象:指的是具备可迭代的能力,即enumerable. 在Python中指的是可以通过for-in 语句去逐个访问元素的一些对象,比如元组tuple,列表list ...
- python yield、yield from与协程
从生成器到协程 协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值.生成器的调用方可以使用 .send(...)方法发送数据,发送的数据会成为yield表达式的值.因此,生成器可以作为协程使 ...
- python协程--yield和yield from
字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...
- 简述 yield和yield from关键字
1.可迭代对象与迭代器的区别 可迭代对象:指的是具备可迭代的能力,即enumerable. 在Python中指的是可以通过for-in 语句去逐个访问元素的一些对象,比如元组tuple,列表list ...
- python yield && scrapy yield
title: python yield && scrapy yield date: 2020-03-17 16:00:00 categories: python tags: 语法 yi ...
- 从yield到yield from再到python协程
yield 关键字 def fib(): a,b = 0,1 while 1: yield b a,b = b,a+b yield是在:PEP 255 -- Simple Generators 这个p ...
随机推荐
- nyoj 118 修路方案(最小生成树删边求多个最小生成树)
修路方案 时间限制:3000 ms | 内存限制:65535 KB 难度:5 描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修 ...
- [iOS UI进阶 - 2.4] 彩票Demo v1.4 转盘动画
A.需求 幸运广场界面中有一个幸运转盘,平时能够自动缓缓转动 能够选择星座 点击“开始选号”开速旋转转盘,旋转一定周数 转盘转动速度节奏:开始-慢-块-慢-结束 设置其余的背景和按钮 code s ...
- GitHub-撤销commit
以下方法适用于:撤销最后一次提交的情况 步骤如下: 步骤1.使用 ”git log“ 命令 找到 想要撤销的操作之前的一次提交的commit id : 比如:使用 git log命令如下结果 comm ...
- Android优化系列之ListView优化老生常谈
本文内容:adapter,listview的优化,RecycleBi,google大会推荐优化, 实现ListView的过程,Adapter起到了至关重要的作用,不仅仅因为getview()方法.那么 ...
- CustomerSOList
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- PostgreSQL的 initdb 源代码分析之十五
继续分析: if (pwprompt || pwfilename) get_set_pwd(); 由于我启动initdb的时候,没有设置口令相关的选项,故此略过. 接下来: setup_depend( ...
- BZOJ 2733: [HNOI2012]永无乡 启发式合并treap
2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- HDU 4821 String hash
String Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- 通过ulimit改善linux系统性能(摘自IBM)
本文介绍了 ulimit 内键指令的主要功能以及用于改善系统性能的 ulimit 用法.通过这篇文章,读者不仅能够了解 ulimit 所起的作用.而且能够学会怎样更好地通过 ulimit 限制资源的使 ...
- 安卓高手之路之 ClassLoader
我不喜欢那些泛泛而谈的去讲那些形而上学的道理,更不喜欢记那些既定的东西.靠记忆去弥补思考的人,容易陷入人云亦云的境地,最后必定被记忆所围困,而最终消亡的是创造力.希望这个高手之路系列能够记录我学习安卓 ...