8

We cannot pass keyword arguments as hash with string keys, keyword arguments works only with hash as symbol keys.

A simple example:

def my_method(first_name:, last_name: )
  puts "first_name: #{first_name} | last_name: #{last_name}"
end

my_method( {last_name: 'Sehrawat', first_name: 'Manoj'}) 
#=> first_name: Manoj | last_name: Sehrawat

my_method( {first_name: 'Bob', last_name: 'Marley'})
#=> first_name: Bob | last_name: Marley

my_method( {'first_name' => 'Kumar', 'last_name' => 'Manoj'})
#=> Error: missing keywords: first_name, last_name (ArgumentError)

What is the reasoning behind it?

Manoj Sehrawat
  • 1,283
  • 1
  • 10
  • 25
  • I think the idea is similar to http://stackoverflow.com/questions/8189416/why-use-symbols-as-hash-keys-in-ruby – freemanoid Feb 12 '15 at 12:15
  • @freemanoid I don't think so. In this case, the syntax is about how to accept a local variable. There is no symbol involved. – sawa Feb 12 '15 at 12:28

3 Answers3

4

The short version would be because Matz says so - on this rubymine issue he comments

I am negative for the proposal. My opinion is that you should not (or no longer) use strings as keywords.

That actual issue is around something that happens as a consequence of this, but if Matz says no it's unlikely to happen. I don't know if he has further expounded on why he is against this.

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
3

The implementation of * and ** could be relevant:

def gather_arguments(*arguments, **keywords)
  puts "arguments: #{arguments.inspect}"
  puts " keywords: #{keywords.inspect}"
end

gather_arguments('foo' => 1, bar: 2, 'baz' => 3, qux: 4)

Output:

arguments: [{"foo"=>1, "baz"=>3}]
 keywords: {:bar=>2, :qux=>4}
Stefan
  • 109,145
  • 14
  • 143
  • 218
  • Are you saying that the string keys are reserved so that they can be distinguished form keyword arguments and interpreted as part of hash arguments? If that is the case, I don't agree. – sawa Feb 12 '15 at 14:52
  • 1
    @sawa I'm not saying this is the reason. Just that the current behavior of `*` and `**` would change (and possibly break existing code), if keyword arguments with string keys were allowed. – Stefan Feb 12 '15 at 14:58
0

Even though keyword arguments can be passed within a hash, I think the primarily intended use is to use the key: value syntax directly:

my_method(first_name: 'Bob', last_name: 'Marley')

As far as this form is concerned, there is no symbol key (or array key) here. The key: value syntax is to directly signify keyword arguments.

My speculation is that, since this syntax coincides with hash with symbol keys and omitted braces, it makes sense to also accept keyword value pairs via hash with symbol keys. And it might be the case that it was designed so to be made compatible with the trick of passing a hash with symbol keys, which was used before this syntax was introduced.

sawa
  • 165,429
  • 45
  • 277
  • 381
  • 1
    The `symbol: key` syntax in 1.9 was indeed introduced *specifically* as a migration path towards "real" keyword arguments. – Jörg W Mittag Feb 12 '15 at 15:04