为什么ruby只允许默认参数和splats的某些排序?

Nie*_*tra 3 ruby

编码ruby时我遇到了一个奇怪的情况:

def foo(bar=true,baz,*args)
end
Run Code Online (Sandbox Code Playgroud)

引发此错误:

syntax error, unexpected tSTAR
Run Code Online (Sandbox Code Playgroud)

而这些:

def foo(bar,baz=true,*args)
end

def foo(bar=true,baz=true,*args)
end
Run Code Online (Sandbox Code Playgroud)

没关系.

为了增加陌生感,这些:

def foo(bar,baz=true)
end

def foo(bar=true,baz)
end
Run Code Online (Sandbox Code Playgroud)

都工作.

但是,这个:

def foo(bar=true,baz,args=true)
end
Run Code Online (Sandbox Code Playgroud)

引发错误,但这些:

def foo(bar=true,baz=true,args)
end

def foo(bar,baz=true,args=true)
end
Run Code Online (Sandbox Code Playgroud)

没事.

我认为有一个合乎逻辑的原因,为什么允许某些组合而其他组合不允许,但我无法通过谷歌或搜索stackoverflow找到它们.我的问题很简单:为什么其中一些组合允许,而其他组合则不允许?

Bor*_*cky 5

那里的Ruby书籍详细解释​​了这一点.但即使没有一个,你也会习惯它的逻辑.一个体面的编码器首先定义强制有序参数的函数,如下所示:

def foo( a, b, c=0, d=0 )
  # ...
end
Run Code Online (Sandbox Code Playgroud)

简单地说,前2个ARGS去a,b和最多2个可选参数传递给c,d在这个顺序.但是你被赋予了超越共同体面的自由:

def foo( a=0, b )
  # ...
end
Run Code Online (Sandbox Code Playgroud)

如果你提供1个参数,那就去了b.如果提供2个指定参数时,他们会被分配到a,b在这个顺序.这不太合适,因为它需要用户更多的学习.如果你自己是用户,那么你就是在猥亵自己,但是,根本就没有语法模糊性.现在看看这个:

def foo( a=0, b, c=0 )
  # ...
end
Run Code Online (Sandbox Code Playgroud)

如果你打电话foo( 1, 2 ),没你的意思是a = 1,b = 2,c = 0,或a = 0,b = 1,c = 2?也许第一个更有可能,但编码规则是,不要猜测用户的意图.所以,Ruby团队可能决定不放纵这种语法.你仍然可以通过定义来实现它:

def foo( *args )
  a, b, c = case args.size
            when 1 then [0, args[0], 0]
            when 2 then [*args, 0]
            when 3 then args
            else fail ArgumentError; "#{args.size} arguments for 1..3!" end
  # ...
end
Run Code Online (Sandbox Code Playgroud)

因此,实际上,您获得了绝对的自由,但Ruby引导您进行良好实践:通过使良好的代码看起来比糟糕的代码更好.同样适用于使用*splat收集参数.体面的案例是明确的:

def foo( a, b=0, *c )
  # ...
end
Run Code Online (Sandbox Code Playgroud)

但是:

def foo( a=0, b, *c )
  # ...
end
Run Code Online (Sandbox Code Playgroud)

当你打电话foo( 1, 2, 3 ),没你的意思是a = 1,b = 2c = [3],或a = 0,b = 1c = [2, 3]?因此,不鼓励这第二种情况,但仍然可以实现:

def foo( *c )
  a, b = case c.size
         when 0 then fail ArgumentError, "Too few arguments!"
         when 1 then [0, c.shift]
         else [c.shift, c.shift] end
  # ...
end
Run Code Online (Sandbox Code Playgroud)

使用许多参数编写函数,特别是使用许多有序参数,这是不好的做法.有句老话说,二元方法比三元方法好,一元优于二元方法,最后,比一元方法更好.如果你的方法需要很多参数,你应该通过用一个对象替换它来重构它.这回答了你的问题了吗?