【问题标题】:Why does double splat only work with symbol keys?为什么 double splat 仅适用于符号键?
【发布时间】:2014-10-01 05:45:18
【问题描述】:

double 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)

为什么仅限于符号键?

这可能与命名关键字符号 a: 3 与符号键哈希的语法糖重合有关,但如上所示,双 splat 与普通哈希符号 :a => 3 一起使用,所以我不是确定这一点。

【问题讨论】:

  • 由于到目前为止还没有人找到原因,我认为没有特别的原因。我在 Ruby bugs.ruby-lang.org/issues/10118 上将此作为功能请求提出。

标签: ruby hash key symbols


【解决方案1】:

我最近遇到了这样的事情。

如果您在 Rails 中,并且您有一个采用关键字参数的方法,并且您有一个强大的参数哈希要发送给它,您可以在参数哈希上使用 symbolize_keys,它会正确分离出参数,不需要双 splat。

型号

class ContactForm
  def initialize(name:, email:)
    @name = name
    @email = email
  end
  # Other stuff
end

控制器

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

【讨论】:

  • 这只是rails,但symbolize_keys方法的主体只是transform_keys{ |key| key.to_sym rescue key },开发人员可以轻松完成
  • 这段代码会引发wrong number of arguments (given 1, expected 0),不是吗?
【解决方案2】:

简短的回答:这就是双 splat 运算符应该捕获的关键字参数在 Ruby 中的表达方式。

长答案:double-splat 运算符用于捕获此答案中所见的关键字:https://stackoverflow.com/a/18289218/3644699

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

您可能遇到的特定错误取决于实施。例如,在 irb 中执行后面的代码 sn-p 会显示引发 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 > 

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

【讨论】:

    猜你喜欢
    • 2011-09-10
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 2011-11-18
    • 2016-01-23
    相关资源
    最近更新 更多