Post

ruby的yield关键字

yield

基础知识看来是需要记录,复习,巩固,加强的。在ruby中关键字yield是一个比较晦涩的东西,也很难清晰的用文字直接来讲解清楚。yield赋予了ruby这门语言及其强大的灵活性和元编程特性,是深度掌握ruby必须要彻底理解的。所以,还是直接上代码

yield和block

1
2
3
4
5
6
7
8
def foo
  yield [1,2,3]
end

foo

yield.rb:2:in `foo': no block given (yield) (LocalJumpError)
        from yield.rb:5:in `<main>'

我们定义了一个方法foo,里面使用了yield关键字,使用方法时会报错,提示没有block参数,所以,yield关键字就是结合block来使用的,yield会调用block来执行block里面的代码

yield执行block

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def foo
   puts "在 test 方法内"
   yield
   puts "你又回到了 test 方法内"
   yield
end

foo {puts "你在块内"}


 test 方法内
你在块内
你又回到了 test 方法内
你在块内

这个例子就可以清晰的看出代码运行顺序,每执行一次yield,就会调用方法携带的block

携带变量的yield

1
2
3
4
5
6
7
8
9
10
11
def test
   yield 5
   puts "在 test 方法内"
   yield 100
end
test {|i| puts "你在块 #{i} 内"}

你在块 5 
 test 方法内
你在块 100 

这个例子可以知道yield时怎么携带参数执行的,yield携带的参数会被赋予给方法携带的block

携带多个变量

1
2
3
4
5
6
7
8
def foo(a,b)
   yield a,b
end

foo(2,3) {|x,y| puts "#{x}, #{y}"}

2,3

同理,yield也可以携带多个参数,block也可以接收多个参数

&变量接收block参数

1
2
3
4
5
6
def foo(&block)
   block.call
end
test { puts "Hello World!"}

Hello World!

在定义方法的时候,可以把block当成一个参数直接定义成方法的参数,用&符号表示这个参数是一个block

注意,所有block参数必须是函数的最后一个参数,必须要放在最后一个位置, 也就是&参数必须是最后一个参数

block不会报错

1
2
3
4
5
6
def foo
  puts "foo inside"
end
foo { puts "foo outside"}

foo inside

这里尝试一下方法不使用yield,但是却携带一个block来调用,可以看到程序并没有报错,只不过携带的block似乎就成了一个没用的参数了,所以要想block生效,函数内部一定要用&变量作为block的接收者,然后才能获取的到block

yield和&变量 两种方式执行block

1
2
3
4
5
6
7
8
def foo
  puts "foo inside"
  yield
end
foo { puts "foo outside"}

foo inside
foo outside

这个例子可以看出,如果想要执行block,就得用yield去调用,所以函数和block的调用有两种方式,一种就是yield,一个就是用&变量显式的接收block,在函数内部进行call调用

小结

用个人的语言描述yield就是,yield在函数里就像一个原材料供应商,而block就是原材料的采购商,yield会告诉它的采购商我给你提供了什么材料,东西给你,至于你把这些材料做成什么东西,那就是你采购商的事了。所以block作为接收者,是最终结果的展示者,而yield作为内部数据提供人员,它只负责数据的提供功能。yieldblock的使用可以说是ruby中的精髓,可以在所有的ruby程序里看见大量的block的调用,所以在看不见的内部,也有无数的yield(以及&变量)在内部起着和block沟通对接的作用。这里只是简单的介绍下,利用这个特性可以非常优雅的实现迭代器,数据交互等功能,实现函数内部和函数外部的功能结合

Ruby相关文章

1. Ruby类基础

2. 类的public private protected

3. Ruby yield

4. Ruby双冒号

This post is licensed under CC BY 4.0 by the author.