Ruby 有关 inject 的一点点`新` 体会.

zw963 · 2012年03月21日 · 最后由 ringokun 回复于 2016年11月25日 · 5400 次阅读

昨天突然对于 inject 有了一些全新的体会。特记录下来,分享。

有关 inject, 之前的想法,一直将其作为一个累加器的替代. 其实,inject 的适用范围远远超出之前对于所谓`注入'的理解。

之前看 Ruby 代码风格的有关文章里面,都建议适用 inject, 应该以下方式:

inject(init) {|a, e| ... } # a表示accumulator, e表示element.

现在想想,这虽然没错,但是这会让人的对于 inject 的理解限制在 a 作为累加器的用途。

事实上,inject 应该这样理解:

将初始化值 init 作为代码块形参传入 a, 经过代码块处理后,并将处理结果重新赋值给 a

很显然,这个 a 并不仅仅扮演了累加器的角色。

甚至可以这样说:inject 更显著的意义在于:

可以完全取代以下方式的代码:

# 以下方式的代码, 应该总是使用inject代替
tmp = 0                            # => 这是一个临时变量.
enum.each {|e| tmp = ... }
# 应该写为:
inject(0) {|tmp, e| tmp = ... }    # => 很明显, 代码块内可以是任何内容. 不仅限于累加.

正如你看到的,更改为 inject 之后,更符合重构的基本定律。(减少了临时变量对外暴露)

不错。。我都没用过 inject 哈哈,完全忘记有这么个东西了。

函数式编程常用的东东,foldl、foldr 一类的。也就是 MapReduce 里的 reduce 算法,确实好用

#1 楼 @ywencn

你真的很直接。哈哈 竟然忘记 inject, 你都敢大声吼出来,我也经常忘,可是我就不告诉别人。

《重构 (Ruby 版)》一书当中,提到了运用 inject 方法实现集合闭包方法。 重构前代码:

def total_charge     result = 0     @rentals.each do |element|         result += element.charge     end     result end

但是通过运用集合闭包方法以及注入的方法还可以进一步简化它。

def total_charge     [email protected](0) {|sum, rental| sum + rental.charge} end

大家应该记住 inject 这个方法,让我们的代码重构变得漂亮

5 楼 已删除

#4 楼 @josh_sulin @前面,少了一个等号

result@rentals.inject(0) {|sum, rental| sum + rental.charge}
替换成result=@rentals.inject(0) {|sum, rental| sum + rental.charge}
需要 登录 后方可回复, 如果你还没有账号请 注册新账号