我试图理解为什么下面的函数会出现编译错误:
# Works fine
def test(a, b=10, c=20)
p a, b, c
end
# Works fine
def test(a=10, b=20, c)
p a, b, c
end
# Gives error - syntax error, unexpected '=', expecting ')'
def test(a=10, b, c=20)
p a, b, c
end
如果多个默认参数都不在参数列表的开头或结尾,则它们似乎不起作用。
答案 0 :(得分:1)
Ruby允许以灵活的方式定义必需参数和可选参数。这些都是合乎逻辑的:
def foo(a); end
def foo(a, b); end
def foo(a, b=1); end
def foo(a=1, b); end
def foo(a=1, b=1); end
如果您需要三个或四个参数,请开始考虑是否应切换到传递参数的其他方式。它是维护和可读性的东西。
而不是任何看起来像
def test(param1=nil, param2, param3, param4, param5, param6, param7, param8, param9, param10)
在此之前的方式,切换到更简洁的东西。任何这些都是更可取的:
def foo(opts)
a, b, c = opts.values_at(*%i[a b c]).map{ |v| v.nil? ? 'nil' : v }
"a: '#{a}' b: '#{b}' c: '#{c}'"
end
foo(a:'a') # => "a: 'a' b: 'nil' c: 'nil'"
foo(a:'a', b:'b') # => "a: 'a' b: 'b' c: 'nil'"
foo(b:'b') # => "a: 'nil' b: 'b' c: 'nil'"
foo(a:'a', b:'b', c: 'c') # => "a: 'a' b: 'b' c: 'c'"
或:
Options = Struct.new('Options', 'a', 'b', 'c')
def foo(opts)
a, b, c = opts.values.map{ |v| v.nil? ? 'nil' : v }
"a: '#{a}' b: '#{b}' c: '#{c}'"
end
foo(Options.new('a', nil, 'c')) # => "a: 'a' b: 'nil' c: 'c'"
foo(Options.new('a', 'b', 'c')) # => "a: 'a' b: 'b' c: 'c'"
foo(Options.new(nil, 'b', 'c')) # => "a: 'nil' b: 'b' c: 'c'"
或:
require 'ostruct'
def foo(opts)
a, b, c = opts.to_h.values_at(*%i[a b c]).map{ |v| v.nil? ? 'nil' : v }
"a: '#{a}' b: '#{b}' c: '#{c}'"
end
foo(OpenStruct.new(:a => 'a')) # => "a: 'a' b: 'nil' c: 'nil'"
foo(OpenStruct.new(:a => 'a', :b => 'b')) # => "a: 'a' b: 'b' c: 'nil'"
foo(OpenStruct.new(:a => 'a', :b => 'b', :c => 'c')) # => "a: 'a' b: 'b' c: 'c'"
使用这种参数传递可以大大降低噪音。在方法内部,您可以查找未初始化的值并强制其默认值和/或如果您没有收到强制值,则会引发错误。
答案 1 :(得分:0)
从this answer related to default parameters翻译参数绑定规则。
Proc
并绑定到块参数raise
和ArgumentError
如果我们仔细阅读上述规则,似乎暗示:
如果您在参数列表的开头或结尾没有强制参数,则所有参数都应该是可选的。
Ruby似乎在以下函数定义中强制执行上述规则:
# Gives error - syntax error, unexpected '=', expecting ')'
def test(a=10, b, c=10)
p a, b, c
end
如果在开始和结束时确实需要可选参数,可以使用类似下面的内容 - 它在开头使用默认参数,在结尾使用关键字参数。
def test(a=10, b=20, c, d: 40, e: 40)
p a, b, c, d, e
end
test (30)
#=> 10, 20, 30, 40, 50
但是,以下内容不起作用:
def test(a=10, b=20, c, d: 40, e: 40, f)
p a, b, c, d, e
end
# Will produce below error
# syntax error, unexpected tIDENTIFIER
# def test(a=10, b=20, c, d: 40, e: 40, f)
^