ruby功能:最佳实践?

时间:2014-01-21 15:03:36

标签: ruby functional-programming

假设我想使用自定义方法选择数组中的元素。为了论证我会使用奇偶校验。

现在一般来说,使用

之间是否有任何良好的做法/建议可供选择
class Integer # Adding method to the Integer class
  def my_fancy_select
    self % 2 == 0
  end
end

puts my_array.select(&:my_fancy_select)

def my_fancy_select(i) # could be a private method
  i % 2 == 0
end

puts my_array.select{|i| my_select(i)}

puts my_array.select{|i| 
  i % 2 == 0 # Directly passing a block
}

,甚至使用Procs?

3 个答案:

答案 0 :(得分:2)

除非您认为该方法真正解决了所有整数的行为,否则应避免添加Integer。即便如此,你也要注意碰撞。

除此之外,没有任何内在的理由选择第二种或第三种形式而不是另一种形式,特别是在你的简单例子中。

代码块和方法提供了不同的代码重用方法。当重复“外部”模式时,块可以很好地工作,并且您只想在内部改变几行。当您需要在多个位置执行完全相同的“内部”逻辑时,方法可以很好地工作。

如果您的过滤逻辑确实在多个地方重复,那么我倾向于将它作为mixin的方法,或者合适的自定义类的类方法,并在块中调用该方法。这是你的第二个例子。否则,带有块的直接单行是适合的目的,我可以在适当的位置阅读它,这提供了一点点可读性优势(假设代码保持DRY) - 这是你的第三个例子。

答案 1 :(得分:2)

一种非常优雅的方法是创建一个具有适当名称的proc或lambda:

even_numbers = -> x {x.even?}
numbers_that_start_with_three = -> x {x.to_s[0] == '3'}

p [11,22,33,4,5,6].select(&even_numbers) #=> [22, 4, 6]
p [11,22,33,4,5,6].select(&numbers_that_start_with_three) #=> [33]

答案 2 :(得分:1)

我看待这样的问题的方式是“是什么让代码最容易阅读和理解?”,因为所有的解决方案都能有效地做同样的事情。

在我看来,我更喜欢这个:

def my_select(i) # could be a private method
  i % 2 == 0
end
puts my_array.select{|i| my_select(i)}

主要是因为它最容易阅读和理解。我也不喜欢“猴子修补”核心类(如Integer),除非没有其他解决方案。