Ruby的块block是ruby的一个重要特性,它能够允许用户将一系列的自定义操作(说白了就是一坨代码)像参数一样传递给方法,接受block块的方法会决定执行块的方式以及次数,在ruby中最常见使用块的地方也就是一些循环的方法,将循环的元素依次用块的逻辑执行一遍,当然具体情况大同小异,你也能自定义自己的能够接受块的方法。
提升代码抽象能力
先来看个简单的例子:
[1, 2, 3, 4, 5].each do |i|
puts i ** 2
end
例子中的意思很明显,循环数组中的每个数字,每次打印这个数字的平方数到标准输出界面。
each方法只是提供一个遍历的方式,具体要执行的逻辑由用户使用的时候具体制定,这其实又一点模版方法的意味在里面,抽象出来的模版方法只提供基础的骨架,具体的方式在使用的时候后绑定,达到一定抽象的目的,当然咯这里只是类比,each返回的其实是一个Enumerator,迭代每个数据的时候会执行块的逻辑。
所以理解块的作用的时候第一个重点应该放在提升代码抽象能力上面,而且避免咯我们把代码写的非常过程化。
代码复用
如标题,block的方式其实也能很好的提供代码复用的能力,同样依例子开始:
>> [1, "5", 2, "7", "3"].sort_by { |a| a.to_i }
=> [1, 2, "3", "5", "7"]
对一个包含数组和字符两种内容的混合数组排序,排序的逻辑是把它们都转换成数字之后进行比较。倘若没有块,我们在实现的时候只能手动循环遍历和转换比较,但这样也就产生一个问题,十种不同方式的排序我们就得实现十次差不多的逻辑(因为只有比较的方式那一行不一样而已),代码会非常冗余和难以维护。
数组从Enumerable模块那mixin的所有方法包括上面例子中的sort_by方法把一些常用的逻辑都包含在里面了,用户在消费集合或者自定义的数据类型的时候通过mixin的方式获得这些抽象处理的方法之后使用的时候能够方便注入自己的逻辑达到想要的效果。
所以代码度用绝对算得上是有块之后一个优雅且实用的功能
自定义带块的方法
自定义一个能够接受使用块的方法非常简单,只需要借助于yield在合理的地方中断和交替执行方法和块的逻辑,而且yield也能很方便的在两者之间传递数据。
yield其实并不是一个多么神奇的东西,说直白点就是暂停当前的逻辑然后转到你设置的其他地方继续执行,next调用的时候再次回到先前暂停的地方,最常用的是用来实现无穷迭代(因为只保存当前信息/状态),其它高级的功能得看具体的语言。
def total(from, to)
result = 0
from.upto(to) do |num|
if block_given?
result += yield(num)
else
result += num
end
end
return result
end
p total(1, 10) #=> 55
p total(1, 10){|num| num ** 2 } #=> 385
关于块的第一部分介绍差不多就是这样,剩下的一些细节,比如块的控制,块局部变量,如何将块封装成Proc对象,接受Proc对象的时候,自定义方法使用封装成Proc对象的块的时候,实现的一些区别,以及Proc带来的像是复用块的逻辑的一些好处吧。
网友评论