为什么双splat只能使用符号键?

saw*_*awa 24 ruby hash symbols key

双splat操作符**似乎只适用于其键是符号的哈希.例如,当键是字符串时,它将不起作用.这两种方式都是如此; 用于施工:

def foo **; end
foo(:a => 3) #=> nil
foo("a" => 3) #=> ArgumentError: wrong number of arguments (1 for 0)
Run Code Online (Sandbox Code Playgroud)

和破坏:

def bar *; end
bar(**{:a => 3}) #=> nil
bar(**{"a" => 3}) #=> TypeError: wrong argument type String (expected Symbol)
Run Code Online (Sandbox Code Playgroud)

为什么它仅限于符号键?

这可能与名为关键字标记的事实a: 3与语法糖与符号键哈希一致,但正如上面看到的那样,双图示的工作原理与普通的散列符号:a => 3,所以我不知道这件事.

小智 7

简短的回答:这就是双重splat运算符应该捕获的关键字参数,用Ruby表示.

答案很长:双重splat运算符用于捕获关键字,如下所示:https://stackoverflow.com/a/18289218/3644699

从Ruby 2.0开始,Ruby支持真正的关键字参数.我的猜测是,在主要实现中,它们仍然表示为Hashes,其键是符号,类似于在语言正式支持它们之前模拟它们的方式.

您获得的特定错误可能取决于实施.例如,在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 > 
Run Code Online (Sandbox Code Playgroud)

hash_merge_kwd是一个内部函数,在这里定义:https://github.com/ruby/ruby/blob/d738e3e15533e0f500789faaedcef9ed9ca362b9/vm.c#L2398


fla*_*001 7

我最近碰到了这样的事情.

如果你在Rails中并且你有一个方法来获取关键字参数并且你有一个强大的params哈希要发送给它,你可以使用symbolize_keysparams哈希并且它将正确地分离出参数,不需要双splat .

模型

class ContactForm
  def initialize(name:, email:)
    @name = name
    @email = email
  end
  # Other stuff
end
Run Code Online (Sandbox Code Playgroud)

调节器

class ContactController < ApplicationController
  def send_mail
    @contact_form = ContactForm.new(contact_params)
    if @contact_form.submit
      # Do stuff
    end
  end

  def contact_params
    params.require(:contact_form).permit(:name, :email).symbolize_keys
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 这只是rails,但是`symbolize_keys`方法的主体只是`transform_keys {| key | key.to_sym抢救密钥}`,开发人员可以轻松完成 (2认同)