这是我的计划:
def calculate(*numbers, options = {})
add(numbers) if options[:add]
subtract(numbers) if options[:add] == false
end
def add(*numbers)
numbers.reduce(:+)
end
def subtract(*numbers)
numbers.reduce(:-)
end
p calculate(1,2)
在第1行,它正在抱怨
tests.rb:1:语法错误,意外'=',期待')'
def计算(*数字,选项= {})
________________________________________________ ^
[以0.1秒完成退出代码1]
我认为Ruby中的默认值可能存在问题,因为在v1.9之前,您需要按顺序拥有所有默认值 - 但这不应该是问题,因为我的版本是
ruby 2.0.0p195 (2013-05-14) [i386-mingw32]
我已经尝试过遍布这些空间,因为当谈到方法时,红宝石似乎特别适合那些东西,但没有骰子。
可能是我的splat变量*numbers
吗?
答案 0 :(得分:10)
splat意味着“用完所有剩余的参数”但是你提供了一个可选的参数,那么解释器如何知道最后一个参数是“数字”splat还是可选的“选项”的一部分?
答案 1 :(得分:8)
感谢@maerics和@JorgWMittag -
当你有一个splat时,它会保留所有参数,这就是为什么它不喜欢我的第二个“选项”参数。我通过改变我的论点来解决这个问题 -
def calculate(*arguments)
options = arguments[-1].is_a?(Hash) ? arguments.pop : {}
options[:add] = true if options.empty?
return add(*arguments) if options[:add]
return subtract(*arguments) if options[:subtract]
end
答案 2 :(得分:6)
在splat参数之后,您只能拥有必需的参数。可选参数必须在splat之前。
Ruby中参数列表的伪正则表达式是这样的:
mand* opt* splat? mand* (mand_kw | opt_kw)* kwsplat? block?
以下是一个例子:
def foo(m1, m2, o1=:o1, o2=:o2, *splat, m3, m4,
ok1: :ok1, mk1:, mk2:, ok2: :ok2, **ksplat, &blk)
Hash[local_variables.map {|var| [var, eval(var.to_s)] }]
end
method(:foo).arity
# => -5
method(:foo).parameters
# => [[:req, :m1], [:req, :m2], [:opt, :o1], [:opt, :o2], [:rest, :splat],
# [:req, :m3], [:req, :m4], [:keyreq, :mk1], [:keyreq, :mk2],
# [:key, :ok1], [:key, :ok2], [:keyrest, :ksplat], [:block, :blk]]
foo(1, 2, 3, 4)
# ArgumentError: missing keywords: mk1, mk2
foo(1, 2, 3, mk1: 4, mk2: 5)
# ArgumentError: wrong number of arguments (3 for 4+)
foo(1, 2, 3, 4, mk1: 5, mk2: 6)
# => { m1: 1, m2: 2, o1: :o1, o2: :o2, splat: [], m3: 3, m4: 4,
# ok1: :ok1, mk1: 5, mk2: 6, ok2: :ok2, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, mk1: 6, mk2: 7)
# => { m1: 1, m2: 2, o1: 3, o2: :o2, splat: [], m3: 4, m4: 5,
# ok1: :ok1, mk1: 6, mk2: 7, ok2: :ok2, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, mk1: 7, mk2: 8)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [], m3: 5, m4: 6,
# ok1: :ok1, mk1: 7, mk2: 8, ok2: :ok2, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, mk1: 8, mk2: 9)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5], m3: 6, m4: 7,
# ok1: :ok1, mk1: 8, mk2: 9, ok2: :ok2, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, 8, mk1: 9, mk2: 10)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8,
# ok1: :ok1, mk1: 9, mk2: 10, ok2: :ok2, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8,
# ok1: 9, mk1: 10, mk2: 11, ok2: :ok2, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8,
# ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12, k3: 13)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8,
# ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12, k3: 13, k4: 14)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8,
# ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13, k4: 14},
# blk: nil }
foo(1, 2, 3, 4, 5, 6, 7, 8,
ok1: 9, ok2: 10, mk1: 11, mk2: 12, k3: 13, k4: 14) do 15 end
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8,
# ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13, k4: 14},
# blk: #<Proc:0xdeadbeefc00l42@(irb):15> }
答案 3 :(得分:3)
def calculate( *numbers, add: true )
add ? add( *numbers ) : subtract( *numbers )
end
def add *numbers; numbers.reduce( 0, :+) end
def subtract n1, n2; n1 - n2 end
calculate 1, 2 #=> 3
calculate 3, 1, add: false #=> 2
答案 4 :(得分:1)
查看extract_options!
在Rails背后的工作原理。
http://simonecarletti.com/blog/2009/09/inside-ruby-on-rails-extract_options-from-arrays/
答案 5 :(得分:1)
实际上,从 Ruby 2.0 ,您可以使用关键字参数来实现此目的。如果您定义一个方法'calculate',如下所示:
def calculate(a, *b, **options)
return a + b.inject(0, :+) if options[:add]
return a + b.inject(0, :-) if options[:subtract]
return 0
end
然后你可以用这个方法调用那个方法:
calculate(3, 4, -5, 3, -8, add: true)
结果你会得到-3。