在Ruby中添加Lisp-Style(+ * args)的最简单方法是什么?

时间:2013-01-15 02:52:53

标签: ruby lisp

所以我真的很喜欢Lisp中的这种语法:

 (+ 1 1 2 3 5 8 13)
 => 33

我想在Ruby中添加一个项目列表,并希望尽可能地近似。 现在,我最好的解决方案涉及一个数组和collect / map方法。

所以:

sum = 0; [1,1,2,3,5,8,13].collect { |n| sum += n }

但是...

我想为此添加可返回nil的方法。

sum = 0; [1, booking_fee, 8,13].collect { |n| n = 0 if n.nil?; sum += n }

这样做真的很好,中间的所有行都引用可能返回nil的方法,但是我不能以这种方式完全构建数组。这只是我想要我的语法的概念。

def total
  Array.new do
    booking_fee
    rental_charges
    internationalization_charges
    discounts
    wild_nights
  end.collect { |n| n = 0 if n.nil?; sum += n }
end

在我试图破解并实现格林斯普规则之前的任何建议? (编程确实是一种强迫。

2 个答案:

答案 0 :(得分:10)

我真的不明白你的问题。如果你想要一个像+那样的方法在Lisp中运行,即取任意数量的参数并且位于前缀位置而不是中缀,这是微不足道的:

def plus(*nums)
  nums.inject(:+)
end

plus 1, 1, 2, 3, 5, 8, 13 # => 33

如果您希望真的花哨,可以覆盖+ s的一元前缀Array运算符:

class Array
  def +@
    inject(:+)
  end
end

+[1, 1, 2, 3, 5, 8, 13] # => 33

请不要这样做!

我不知道你的问题的其余部分是如何与Lisp风格的加法操作相关的。

如果您要从nil中删除Array,那么Array#compact就可以了。

答案 1 :(得分:4)

  • 已经有一种方法inject用于做你想做的事。
  • nil更改为不影响数字的数字很简单:使用to_i(如果您正在处理浮动,请使用to_f。)

[
  booking_fee,
  rental_charges,
  internationalization_charges,
  discounts,
  wild_nights,
].inject(0){|sum, item| sum + item.to_i}