def method(a, b='a', c, *d)
[a,b,c, d]
end
p method(1,2,3,4)
不起作用,我不明白为什么,如果我们删除b参数一切正常。语法规则说你可以在splat参数之前使用默认值设置params。
答案 0 :(得分:4)
具有默认值和splat变量的变量可以存在并且共存,只要具有默认值的变量可以被解释为(唯一的)splat的初始元素。
因此,这些都可以工作:
def good(a = :a, b); [a,b]; end
def good(a = :a, *b); [a,b]; end
def good(a, b = :b, *c); [a,b,c]; end
但这些不会:
def bad(*a, b = :b); [a,b]; end # default after the splat
def bad(a = :a, b, c = :c); [a,b,c]; end # parsing would need two splats
def bad(a = :a, b, *c); [a,b,c]; end # parsing would need two splats
def bad(*a, b = :b, c); [a,b,c]; end # default after the splat
(Tbh,我不知道哪些实现细节会阻止Ruby在 splat之后立即接受默认值,前提是没有歧义。但我猜这是为了避免在splat上循环两次而不是一次,即性能,并且可能有其他原因可能与Ruby计算方法的方式有关。)
答案 1 :(得分:3)
默认参数(b
)应位于位置参数(a
,c
)之后:
def method(a, c, b='a', *d)
[a,b,c, d]
end
答案 2 :(得分:0)
幕后发生了一些事情:
def method(a=7, b, *c); end
SyntaxError: (irb):25: syntax error, unexpected *
def method(a=7, b, *c); end
^
def method(*b, *c); end
SyntaxError: (irb):26: syntax error, unexpected *
def method(*b, *c); end
^
请注意,这是同一个错误。当你将一个默认值的param放在固定参数列表末尾以外的任何地方时,我希望内部Ruby使用相同的结构来表示它用于splat的内容(Ruby C API方法是{{ 1}})。因此,由于对多个splats的相同限制,您不能拥有中间位置默认值。
AFAICS,这不是语言的技术限制,但实现细节 - 巧妙处理Ruby中非结束位置的默认值是重用splats使用的数据结构和逻辑。 splats 有以这种方式受限制(因为两个splats是不明确的),但理论上可能有一个方案支持你的问题中的默认值。可能虽然这是一个不寻常的要求,你不会在不久的将来看到它完成。我建议只需将你的命名可选参数移到splat param之前。