ruby 为什么双劈啪声只对符号关键点起作用?

6tdlim6h  于 2023-01-25  发布在  Ruby
关注(0)|答案(3)|浏览(119)

双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与带有符号键的散列语法sugar一致有关,但是如上所述,双splat与普通散列表示法:a => 3一起工作,所以我不确定这一点。

inb24sb2

inb24sb21#

我最近遇到过这样的事。
如果你在Rails中,你有一个接受关键字参数的方法,你有一个强params散列,你想发送给它,你可以在params散列上使用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
pgvzfuti

pgvzfuti2#

简短的回答是:这就是关键字参数(double-splat操作符应该捕获的参数)在Ruby中的表达方式。
长长的回答:double-splat操作符用于捕获关键字,如以下答案所示:https://stackoverflow.com/a/18289218/3644699
从Ruby 2.0开始,Ruby就支持真关键字参数,我猜在主实现中,它们仍然被表示为散列,其键是符号,类似于在语言正式支持它们之前模拟它们的方式。
具体的错误可能取决于实现,例如,在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 >

hash_merge_kwd是一个内部函数,定义如下:www.example.comhttps://github.com/ruby/ruby/blob/d738e3e15533e0f500789faaedcef9ed9ca362b9/vm.c#L2398

cgvd09ve

cgvd09ve3#

从2.7版开始它在ruby中工作

相关问题