Ruby 《Ruby 元编程》读书笔记 (十六)[连载完结]

lazybios · 2015年09月23日 · 最后由 ecloud 回复于 2017年06月14日 · 3146 次阅读

这篇是这个系列的完结贴,从第一章到最后的附录,每章节的重点知识都有罗列,整个过程下来获益匪浅,强烈建议每位 Rubyist 都能花些时间阅读一下这本书,别的不敢说,至少能保证你看别人代码时,不被绕晕,同时学习一点元编程的知识,在写 Rails 代码的过程中,也更有利于定位问题。最后感谢各位看官捧场!:)

博客地址 :《Ruby 元编程》读书笔记 (十六)

相关文章:

《Ruby 元编程》读书笔记 (一) 《Ruby 元编程》读书笔记 (二) 《Ruby 元编程》读书笔记 (三) 《Ruby 元编程》读书笔记 (四) 《Ruby 元编程》读书笔记 (五) 《Ruby 元编程》读书笔记 (六) 《Ruby 元编程》读书笔记 (七) 《Ruby 元编程》读书笔记 (八) 《Ruby 元编程》读书笔记 (九) 《Ruby 元编程》读书笔记 (十) 《Ruby 元编程》读书笔记 (十一) 《Ruby 元编程》读书笔记 (十二) 《Ruby 元编程》读书笔记 (十三) 《Ruby 元编程》读书笔记 (十四) 《Ruby 元编程》读书笔记 (十五)

传神的头图↓↓↓

Ruby元编程

Self Yield

给一个方法传入代码块时,可以通过 yield 占位对块进行回调。除了直接调用块外,还可以通过 yeild 给代码块传递参数,这个 self yield 的惯用法,其实就是通过 yield self,把自身 (当前对象) 传递给代码块。

使用 tap 调试方法调用链

[a,b,c].push(d).shift.tap {|x| puts x}.upcase.next
#输出
a

这里的 tap 方法就是利用了 self yield 技术,将自己传给代码块,从而让我们能打印出当前的状态值,辅助调试方法调用链,避免“火车失事”问题。

Kernel#tap的定义和文档描述如下:

tap{|x|...}  obj

Yields self to the block, and then returns self.** The primary purpose of this method is to “tap into” a method chain, in order to perform operations on intermediate results within the chain.**

不过自己实现一个 tap 方法也不难:

class Object
    def tap
        yield self
        self
    end
end

Symbol#to_proc方法

Symbol#to_proc方法的目的是位了用更简单的方式来替代一次调用代码块。所谓的一次调用代码块是指那些只有一个参数,且对这个参数只调用一个方法。如下:

names = [bob, bill, heather]
names.map{ | name | name.capitalize } #=> [“Bob”, “Bill”, “Heather”]

那么Symbol#to_proc方法又是怎么做到精简的呢?继续往下看

names = [bob, bill, heather]
names.map(&:capitalize) #=> [“Bob”, “Bill”, “Heather”]

上面出现了&符号,&符号的含义是:这是一个 Proc 对象,我想把它当成代码块来使用。去掉&符号,将能再次得到一个 Proc 对象。&符号可以用作任何对象,它会调用该对象的 to_proc 方法来把这个对象转换为一个 Proc,之后 map 方法会将 names 数组中的每个值作为这个 Proc 对象的参数进行调用。

class Symbol
    def to_proc
        Proc.new { |x| x.send(self) }
    end
end

用到了动态派发,to_proc 方法会返回一个 Proc 对象,该对象会在传入的参数上执行:method_name(符号方法,因为动态调用的是 self,符号对象本身)。

此外,Ruby 中的对象还支持多于一个参数的块,类似 inject 方法 (ps: 这里还不是很熟),见下面代码。

[1,2,5].inject(0) { | memo, obj | memo + obj } #=> 8
[1,2,5].inject(0, &:+) #=> 8

-完-

=============== 最后贴一下自己的公众账号

可以十日不将军,不可一日不拱卒,日拱一卒 (rigongyizu365)

感谢楼主辛苦的整理,请管理员考虑是否可以加到 wiki?

#2 楼 @douxiance 多谢你的持续关注 😁

楼主写了很多东西,感谢楼主分享。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号