3

在 Ruby 2.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}

但是尝试将 Hash 作为位置参数传递,会发生这种情况:

irb(main):002:0> example({something: 42})
[]
{:something=>42}

*args想拿{something: 42},没有**kwargs

位置参数必须是可选的,但即使*argsarg=nil,双 splat 仍然太贪婪:

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"}

当该方法也采用时,如何将哈希作为位置参数传递**

4

1 回答 1

2

这总是很难管理,因为**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
于 2017-07-10T17:21:59.587 回答