Ruby 为什么双splat仅适用于符号键?

Ruby 为什么双splat仅适用于符号键?,ruby,hash,key,symbols,Ruby,Hash,Key,Symbols,双splat运算符**似乎只适用于键为符号的哈希。例如,当键是字符串时,它将不起作用。这两种情况都是如此;建筑方面: def foo **; end foo(:a => 3) #=> nil foo("a" => 3) #=> ArgumentError: wrong number of arguments (1 for 0) def bar *; end bar(**{:a => 3}) #=> nil bar(**{"a" => 3}) #=>

双splat运算符
**
似乎只适用于键为符号的哈希。例如,当键是字符串时,它将不起作用。这两种情况都是如此;建筑方面:

def foo **; end
foo(:a => 3) #=> nil
foo("a" => 3) #=> ArgumentError: wrong number of arguments (1 for 0)
def bar *; end
bar(**{:a => 3}) #=> nil
bar(**{"a" => 3}) #=> TypeError: wrong argument type String (expected Symbol)
和销毁:

def foo **; end
foo(:a => 3) #=> nil
foo("a" => 3) #=> ArgumentError: wrong number of arguments (1 for 0)
def bar *; end
bar(**{:a => 3}) #=> nil
bar(**{"a" => 3}) #=> TypeError: wrong argument type String (expected Symbol)
为什么它仅限于符号键


这可能与命名关键字表示法a:3与符号键哈希的语法sugar一致有关,但如上所述,双splat与普通哈希表示法a=>3一起工作,因此我对此不确定。

简短的回答是:关键字参数就是这样,double-splat操作符应该捕获的是用Ruby表示的

长答案:双splat操作符用于捕获关键字,如此答案所示:

自Ruby 2.0以来,Ruby支持true关键字参数。我的猜测是,在主要实现中,它们仍然表示为哈希,其键是符号,类似于在语言正式支持它们之前模拟它们的方式

您可能遇到的特定错误取决于实现。例如,在irb中执行后一个代码段将显示引发TypeError的函数:

2.1.2 :001 > def bar *; end
 => :bar 
2.1.2 :002 > bar(**{"a" => 3})
TypeError: wrong argument type String (expected Symbol)
    from (irb):2:in `core#hash_merge_kwd'
    from (irb):2
    from /home/mkis/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :003 > 
2.1.2:001>def bar*;结束
=>:巴
2.1.2:002>bar(**{“a”=>3})
TypeError:参数类型字符串错误(应为符号)
from(irb):2:in'core#hash(散列)merge(合并)kwd'
来自(irb):2
from/home/mkis/.rvm/rubies/ruby-2.1.2/bin/irb:11:in`'
2.1.2 :003 > 

hash\u merge\u kwd
是一个内部函数,在这里定义:

我最近遇到了类似的情况

如果您在Rails中,并且您有一个接受关键字参数的方法,并且您有一个要发送给它的强params散列,那么您可以在params散列上使用
symbol_keys
,它将正确地分离出参数,而不需要双重splat

模型 控制器
class ContactController
由于到目前为止还没有人找到原因,我认为没有特别的原因。我在Ruby上请求这个功能。这只是rails,但是
符号键
方法的主体就是
转换键{key{key.to{sym rescue key}
,开发人员可以很容易地完成。这段代码将引发
错误数量的参数(给定1,预期为0)
,不是吗?