0

I realize symbol keys in a hash are immutable whereas string keys are mutable, but I still don't understand why that would cause these results ...

[5] pry(main)> a[:b] = "c"
=> "c"
[6] pry(main)> a["b"]
=> nil
[7] pry(main)> a[:b]
=> "c"

Shouldn't "a[:b]" get turned into a["b"] under the hood?

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
Dave
  • 15,639
  • 133
  • 442
  • 830
  • 1
    Why do you expect one object to be silently converted into another “under the hood”? The question sounds to me like “should not `42` to be turned into `[:foo, :bar]` under the hood?”. – Aleksei Matiushkin Dec 20 '19 at 16:10
  • Maybe I should have put, what is happening under the hood? Is the key ":b" treated as an immutable string, "b"? – Dave Dec 20 '19 at 16:15
  • 1
    Basically, `"b"` and `:b` have nothing in common. I mean, _nothing_. – Aleksei Matiushkin Dec 20 '19 at 16:17
  • @Dave no, it's not, `:b` is treated like `:b`. – Marek Lipka Dec 20 '19 at 16:17
  • 1
    Maybe you have a different point of view since the use of Rails and its `with_indifferent_access` method? But no, I think there's no case where `"b"` is equal to `:b`. They're pretty much different objects. – Sebastián Palma Dec 20 '19 at 16:17
  • BTW 'string keys are mutable' - not always, you can easily make your strings immutable by `freeze` method. There's even magic comment - `# frozen_string_literal: true`, that causes implicit immutability of any string literal put in the same file. – Marek Lipka Dec 20 '19 at 16:30

1 Answers1

2

No, it shouldn't, :b is a different object than 'b', so unless a is a hash with indifferent access, a[:b] will most likely return different result than a['b'].

BTW althouth Ruby is in fact dynamically typed, it's also quite strongly typed - implicit type conversion occurs rather rarely here.

Marek Lipka
  • 50,622
  • 7
  • 87
  • 91
  • Thank you. I know it's different due to the results I put in my question. My question is why is it different? What's happening under the hood with the hash keys that are causing different hash values? – Dave Dec 20 '19 at 16:14
  • Why shouldn't it be different? – Marek Lipka Dec 20 '19 at 16:16
  • Because I read the key ":b" is treated as an immutable string "b" under the hood. Is that what is happening? – Dave Dec 20 '19 at 16:18
  • @Dave no, not really. It's more like 'scalar value object used as identifiers, mapping immutable string to fixed internal value', not 'immutable string' itself. – Marek Lipka Dec 20 '19 at 16:21
  • Oh! Ok, I'll have to read up on scalar value objects but that explains it. Thx! – Dave Dec 20 '19 at 16:24
  • 1
    @Dave If you want the behaviour as defined in your question you have to use [`HashWithIndifferentAccess`](https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html) which can be achieved through `ActiveSupport::HashWithIndifferentAccess.new({a: 1, b: 2})` or `{a: 1, b: 2}.with_indifferent_access`. – 3limin4t0r Dec 20 '19 at 17:33