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
作为内部数据提供人员,它只负责数据的提供功能。yield
和block
的使用可以说是ruby
中的精髓,可以在所有的ruby
程序里看见大量的block
的调用,所以在看不见的内部,也有无数的yield
(以及&
变量)在内部起着和block
沟通对接的作用。这里只是简单的介绍下,利用这个特性可以非常优雅的实现迭代器,数据交互等功能,实现函数内部和函数外部的功能结合