Why does double splat only work with symbol keys? Why does double splat only work with symbol keys? ruby ruby

Why does double splat only work with symbol keys?


I ran into something like this recently.

If you're in Rails and you have a method that takes keyword arguments and you have a strong params hash that you want to send to it, you can use symbolize_keys on the params hash and it will properly separate out the arguments, no double splat needed.

Model

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

Controller

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  endend


The short answer: that's how keyword arguments, which the double-splat operator is supposed to capture, are expressed in Ruby.

The long answer: the double-splat operator is for capturing keywords as seen in this answer: https://stackoverflow.com/a/18289218/3644699

Since Ruby 2.0, Ruby supports true keyword arguments. My guess is that in the main implementation they are still represented as Hashes whose keys are symbols, similar to how they were simulated before the language officually supported them.

The particular errors you're getting likely depend on implementation. For example, executing the latter code snippet in irb shows the function that raises the 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 is an internal function, defined here: https://github.com/ruby/ruby/blob/d738e3e15533e0f500789faaedcef9ed9ca362b9/vm.c#L2398