yield

所有的"方法(methods)"隐式跟上一个"块(block)"参数。

块参数也可以明确给定,形式就是在参数前面加一个"&",比如 def fn(arg1, arg2, &block) end,其中的 &block 就是明确给定的块参数。

块参数的动作,可以通过调用 call() 方法执行,还可以用 yield 来执行 —— yield 其实就是一个语法糖。

所以以下几种写法常常是等价的:

  1. #method receives an invisible block argument
  2. def foo1()
  3. yield 1
  4. end
  5.  
  6. #specify it explicitly
  7. def foo2(&block)
  8. yield 1
  9. end
  10.  
  11. #yield is equal to block.call
  12. def foo3(&block)
  13. block.call(1)
  14. end
  15.  
  16. #function call
  17. foo1 {|x| puts x} # =>
  18. foo2 {|x| puts x} # =>
  19. foo3 {|x| puts x} # =>

Proc

前面说到所有方法都可以隐式或显式指定一个块参数,那么块参数到底是什么呢?

答案是 Proc 对象,一个具有 call 方法的对象。

Proc 对象的定义有几种形式:

  • 直接使用 {}
  • 使用 Proc.new {}
  • 使用 proc {}
  • 使用 lambda {}
  1. #yield is equal to block.call
  2. def foo(&block)
  3. puts block.class
  4. puts block.to_s
  5. yield 1
  6. end
  7.  
  8. #function call
  9. # Proc created using {} syntax
  10. foo {|x| puts x}
  11. # => Proc
  12. # => #<Proc:0x00000000e0b140@(ruby):9>
  13. # =>
  14.  
  15. # Proc created with the "proc" keyword. Note & syntax when calling.
  16. my_proc = proc { |n| puts n }
  17. foo(&my_proc)
  18. # => Proc
  19. # => #<Proc:0x00000000e0b140@(ruby):12>
  20. # =>
  21.  
  22. # Proc creates with Proc.new
  23. my_proc = Proc.new { |n| puts n }
  24. foo(&my_proc) # => 1
  25. # => Proc
  26. # => #<Proc:0x00000000e0b140@(ruby):16>
  27. # =>
  28.  
  29. # Proc created with the "lambda" keyword. Nearly same thing.
  30. my_proc = lambda { |n| puts n }
  31. foo(&my_proc)
  32. # => Proc
  33. # => #<Proc:0x00000000e0b140@(ruby):20 (lambda)>
  34. # =>

yield self

在一个对象中,self 表示是一个当前对象的引用。

所以,常见的 yield self if block_given? 中的 self 就和其它地方使用 self 一样,没什么特殊的。

  1. class C1
  2. def foo(&block)
  3. puts block.class
  4. puts block.to_s
  5. yield self if block_given?
  6. yield "AAAAAAAAA"
  7. end
  8. end
  9.  
  10. class C2
  11. def foo(&block)
  12. puts block.class
  13. puts block.to_s
  14. yield self if block_given?
  15. yield "BBBBBBBBB"
  16. end
  17.  
  18. def to_s
  19. "XXXXXXXXXX"
  20. end
  21. end
  22.  
  23. c1 = C1.new
  24. c1.foo {|x| puts x}
  25. # => Proc
  26. # => #<Proc:0x00000001c84aa0@(ruby):23>
  27. # => #<Context::C1:0x00000001c84af0>
  28. # => AAAAAAAAA
  29.  
  30. c2 = C2.new
  31. c2.foo {|x| puts x}
  32. # => Proc
  33. # => #<Proc:0x00000001c842f8@(ruby):26>
  34. # => XXXXXXXXXX
  35. # => BBBBBBBBB

注意事项

method 定义中 &block 参数必须在最后

  1. # 正确示例
  2. def foo(arg1, arg2, &block)
  3. puts block
  4. end
  5.  
  6. #function call
  7. block = proc {|x| puts x}
  8. foo( 1, 2, &block)
  9. # => #<Proc:0x000000011f3aa0@(ruby):14>
  10.  
  11. #错误示例
  12. def foo(arg1, &block, arg2) # => (ruby): syntax error
  13. puts block
  14. end

yield 相当于是 block.call() 方法的调用,所以参数个数也需要对应

  1. def foo()
  2. yield 1,2,3 # 这里的 1 2 3 就是传递的参数
  3. end
  4.  
  5. #function call
  6. foo {|x| puts x} # => 1
  7. foo {|x,y,z| puts z} # => 3
  8. foo {|x,y,z,k| puts k} # 为空

ruby 疑难点之—— yield 和 yield self的更多相关文章

  1. python yield 与 yield from转

    python yield 与 yield from转 https://blog.csdn.net/chenbin520/article/details/78111399?locationNum=7&a ...

  2. yield与yield from

    yield 通过yield返回的是一个生成器,yield既可以产出值又可以生成值,yield可以用next()来启动生成器,同时可以用send向生成器传递值:在初次启动生成器时,需调用next()或s ...

  3. 从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 ...

  4. 60、简述 yield和yield from关键字。

    1.可迭代对象与迭代器的区别 可迭代对象:指的是具备可迭代的能力,即enumerable.  在Python中指的是可以通过for-in 语句去逐个访问元素的一些对象,比如元组tuple,列表list ...

  5. python yield、yield from与协程

    从生成器到协程 协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值.生成器的调用方可以使用 .send(...)方法发送数据,发送的数据会成为yield表达式的值.因此,生成器可以作为协程使 ...

  6. python协程--yield和yield from

    字典为动词“to yield”给出了两个释义:产出和让步.对于 Python 生成器中的 yield 来说,这两个含义都成立.yield item 这行代码会产出一个值,提供给 next(...) 的 ...

  7. 简述 yield和yield from关键字

    1.可迭代对象与迭代器的区别 可迭代对象:指的是具备可迭代的能力,即enumerable.  在Python中指的是可以通过for-in 语句去逐个访问元素的一些对象,比如元组tuple,列表list ...

  8. python yield && scrapy yield

    title: python yield && scrapy yield date: 2020-03-17 16:00:00 categories: python tags: 语法 yi ...

  9. 从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 ...

随机推荐

  1. nyoj 118 修路方案(最小生成树删边求多个最小生成树)

    修路方案 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修 ...

  2. [iOS UI进阶 - 2.4] 彩票Demo v1.4 转盘动画

    A.需求 幸运广场界面中有一个幸运转盘,平时能够自动缓缓转动 能够选择星座 点击“开始选号”开速旋转转盘,旋转一定周数 转盘转动速度节奏:开始-慢-块-慢-结束 设置其余的背景和按钮   code s ...

  3. GitHub-撤销commit

    以下方法适用于:撤销最后一次提交的情况 步骤如下: 步骤1.使用 ”git log“ 命令 找到 想要撤销的操作之前的一次提交的commit id : 比如:使用 git log命令如下结果 comm ...

  4. Android优化系列之ListView优化老生常谈

    本文内容:adapter,listview的优化,RecycleBi,google大会推荐优化, 实现ListView的过程,Adapter起到了至关重要的作用,不仅仅因为getview()方法.那么 ...

  5. CustomerSOList

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  6. PostgreSQL的 initdb 源代码分析之十五

    继续分析: if (pwprompt || pwfilename) get_set_pwd(); 由于我启动initdb的时候,没有设置口令相关的选项,故此略过. 接下来: setup_depend( ...

  7. BZOJ 2733: [HNOI2012]永无乡 启发式合并treap

    2733: [HNOI2012]永无乡 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  8. HDU 4821 String hash

    String Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  9. 通过ulimit改善linux系统性能(摘自IBM)

    本文介绍了 ulimit 内键指令的主要功能以及用于改善系统性能的 ulimit 用法.通过这篇文章,读者不仅能够了解 ulimit 所起的作用.而且能够学会怎样更好地通过 ulimit 限制资源的使 ...

  10. 安卓高手之路之 ClassLoader

    我不喜欢那些泛泛而谈的去讲那些形而上学的道理,更不喜欢记那些既定的东西.靠记忆去弥补思考的人,容易陷入人云亦云的境地,最后必定被记忆所围困,而最终消亡的是创造力.希望这个高手之路系列能够记录我学习安卓 ...