2

我正在尝试为 Rubymonk 的 Ruby 练习编写自己的解决方案,其目的是创建三种方法(加法、减法和计算),因此当调用“计算”​​时,您可以根据传入了什么。我收到以下错误:

main:11: syntax error, unexpected '=', expecting ')' def calculate(*numbers, options={})

谁能告诉我我的代码有什么问题?感谢您的任何帮助!

def add(*numbers)
  numbers.inject(0) {|sum, number| sum + number}
end

def subtract(*numbers)
  numbers.inject{|diff, number| diff - number}
end

def calculate(*numbers, options={})
  result = add(numbers) if options.empty?
  result = add(numbers) if options[:add]
  result = subtract(numbers) if options[:subtract]
  result
end
4

4 回答 4

4
def calculate(*numbers, options={})

不是一个有效的方法定义 b/c*numbers代替可变数量的参数。在我看来,您有两个选择-

def calculate(options={}, *numbers)

或者

def calculate(*args)
   numbers, options = args[0..-2], args[-1] || {}

如果你想保持相同的参数顺序

于 2013-10-31T18:37:26.873 回答
0

试试这个方法:
def calculate(options={},*numbers)

在完全可选参数( * 符号)之后使用可选参数不起作用,因为它会产生歧义。

阅读更多:

http://www.skorks.com/2009/08/method-arguments-in-ruby/

于 2013-10-31T18:42:53.213 回答
0

splat 参数*numbers必须是最后一个参数。否则,Ruby 怎么知道何时将最后一个参数视为options最后一个数字?

您可以使用(*numbers, options)(没有默认值),但这需要您始终将选项哈希传递给该方法(否则您的最后一个数字将被设置为options变量)。

于 2013-10-31T18:36:21.343 回答
0

您不能同时使用 splat 和带有默认值的参数作为最后一个参数,这对于解析器来说太模棱两可了(如何知道传递的最后一个参数是选项?)

您可以通过多种方式解决此问题;rails(主动支持)的一个成语是:

def calculate(*args)
  options = args.extract_options!
  # ...
end

哪里extract_options!ArrayActiveSupport定义如下的猴子补丁:

def extract_options!
  last.is_a?(::Hash) ? pop : {}
end

作为旁注:

  • 选项哈希在这里并不是很有用。你可以只传入一个符号作为第一个参数,也许。
  • 如果您使用哈希,逻辑可能会更简单:

     def calculate(*args)
       options = args.extract_options!
       method = options.fetch(:method, :add)
       send method, *args
     end
    
  • on add,您不需要inject(0)inject如果您不提供一个,则使用数组的第一个元素作为第一个“备忘录”值

  • 您可以传递一个符号来注入,这将是在您的“备忘录”值上调用的方法,以“下一个值”作为参数:

     (1..10).inject(:+)
    
     # this is the same as 
     (1..10).inject{ |memo, next| memo + next }
    
     # or, more exactly
     (1..10).inject{ |memo, next| memo.send :+, next }
    
于 2013-10-31T19:07:32.913 回答