Ruby double splat 参数对于 Hash 参数来说太贪心了
Ruby double splat parameter is too greedy with Hash argument
在Ruby2.4.1中,我有这样的方法:
def example(*args, **kwargs)
p args
p kwargs
end
我可以传递 不是 哈希的位置参数就好了:
irb(main):001:0> example("Greetings")
["Greetings"]
{}
如果我想使用命名参数,那也没关系:
irb(main):002:0> example(something: 42)
[]
{:something=>42}
但是尝试将哈希作为位置参数传递时,会发生这种情况:
irb(main):002:0> example({something: 42})
[]
{:something=>42}
我希望*args
接受{something: 42}
,而不是**kwargs
。
位置参数必须是可选的,但即使 *args
是 arg=nil
,双拼仍然太贪心了:
irb(main):001:0> def example(arg=nil, **kwargs)
irb(main):002:1> p arg
irb(main):003:1> p kwargs
irb(main):004:1> end
=> :example
irb(main):005:0> example({"key":"value"})
nil
{:key=>"value"}
irb(main):006:0> example({"key":"value"}, this_is: "in kwargs")
{:key=>"value"}
{:this_is=>"in kwargs"}
当该方法也采用 **
时,如何将哈希作为位置参数传递?
管理起来总是很棘手,因为这里的 **kwargs
会主动取得该散列的所有权。这也给调用者带来了一些困惑,因为无论你做什么,他们在调用它时都必须小心:
# Is this options or the body? It's not clear.
example({ payload: true })
我建议切换到更明确的内容,例如:
def example(**kwargs)
body = kwargs.delete(:body)
end
然后这样调用它:
example(body: { ... }, user: "username", ...)
如果你能说出允许的参数,那就更好了:
def example(body: nil, user: nil, password: nil)
# ...
end
在Ruby2.4.1中,我有这样的方法:
def example(*args, **kwargs)
p args
p kwargs
end
我可以传递 不是 哈希的位置参数就好了:
irb(main):001:0> example("Greetings")
["Greetings"]
{}
如果我想使用命名参数,那也没关系:
irb(main):002:0> example(something: 42)
[]
{:something=>42}
但是尝试将哈希作为位置参数传递时,会发生这种情况:
irb(main):002:0> example({something: 42})
[]
{:something=>42}
我希望*args
接受{something: 42}
,而不是**kwargs
。
位置参数必须是可选的,但即使 *args
是 arg=nil
,双拼仍然太贪心了:
irb(main):001:0> def example(arg=nil, **kwargs)
irb(main):002:1> p arg
irb(main):003:1> p kwargs
irb(main):004:1> end
=> :example
irb(main):005:0> example({"key":"value"})
nil
{:key=>"value"}
irb(main):006:0> example({"key":"value"}, this_is: "in kwargs")
{:key=>"value"}
{:this_is=>"in kwargs"}
当该方法也采用 **
时,如何将哈希作为位置参数传递?
管理起来总是很棘手,因为这里的 **kwargs
会主动取得该散列的所有权。这也给调用者带来了一些困惑,因为无论你做什么,他们在调用它时都必须小心:
# Is this options or the body? It's not clear.
example({ payload: true })
我建议切换到更明确的内容,例如:
def example(**kwargs)
body = kwargs.delete(:body)
end
然后这样调用它:
example(body: { ... }, user: "username", ...)
如果你能说出允许的参数,那就更好了:
def example(body: nil, user: nil, password: nil)
# ...
end