Issue #14336 has been updated by rosenfeld (Rodrigo Rosenfeld Rosas).


Matz, if you don't mind, I'd like to give your questions a try:

>So, to persuade me, you have to answer following questions very clearly, concretely:

> why do you want that change? (I am sick of "make sense" or "natural" or "consistent")

Serializing values to and from JSON is becoming a very very common operation no matter what languages you are using. We do that all the time. It often leads to confusion in Ruby programs if the original hash being serialized had keys as symbols and after deserialization they are strings, which means one would have to re-convert them to symbols, for example. This sort of confusion happens in several other situations, including some hashes we get from other's code and the only way we can know if keys are expecting to be string or symbol is by either giving it a try or looking into the documentation (if any) or tracking down the code until we know what to expect. This is very costly and could be avoided if h[:a] == h['a']. So, my main motivation is to make it easier for most Rubyists to write code without having to waste too much time thinking about symbols and strings.

how big is the impact of the change? (compatibility, performance)

It can be big or small. Since I know you won't consider big incompatibilities, I'm interpreting this question as "how can we reduce the impact of the change?".

If we use the same approach taken by the frozen strings magical comment and apply it to symbols, the impact would be minimal. Making the comparison of strings and symbols work seamless based on such magical comments or flags seem complicated and they could introduce more incompatibilities, so I'd like to focus on the main issue as I see: h[:a] != h['a'].

For that, I'd propose a new flag/magical comment such as "# hwia_by_default: true". A new read-only property (set at creation time) would be added to Hash such as :indifferent_access. Example: `h = Hash.new({a: 1}, indifferent_access: true)`. Alternatively we could add a method to Hash to return a copy with this property set: `new_hash = hash.with_indifferent_access; new_hash.has_indifferent_access? # true`. Those names are just suggestions and they are not important for the time being. We can always discuss better names. For now, let me explain the idea on how that would work.

~~~ ruby
# hwia_by_default: true

h = {a: 1} # translated to Hash.new({a: 1}, indifferent_access: true)
assert h[:a] == h['a']
~~~

It would be even better if we could add a short syntax to create such hashes when we can't add the magical comment:

~~~ ruby
h = {a: 1}i # equivalent of Hash.new({a: 1}, indifferent_access: true)
~~~

So, with regards to compatibility it seems we would be fine since such approach shouldn't break existing code.

Regarding performance, this is not that simple to answer. I can't tell about internal performance since I'm not an implementor, but just take into consideration that lots of application have to convert hash keys between symbols and strings and that should be taken into consideration when evaluating the performance impact. If one often has to call `transform_keys` (or ActiveSupport's `symbolize_keys`) when not using the new flag, that should be taken into consideration when evaluating the performance impact.

> how big is the benefit of the change?

It sounds huge to me. Not having to worry about using symbols or strings as keys look like a huge win to my happinness when coding less buggy prone applications. And by inspecting some articles and questions and complains in StackOverflow it seems I'm not alone in thinking this way.

> who gets the benefit?

Most (if not all) Rubyists in my opinion.

> who gets the penalty?

The language implementors, maybe?

> after considering above questions, is the change reasonable?

Definitely yes, if you ask me ;)

----------------------------------------
Feature #14336: Create new method String#symbol? and deprecate Symbol class
https://bugs.ruby-lang.org/issues/14336#change-69550

* Author: dsferreira (Daniel Ferreira)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
From  the discussions on the three previous issues related to the String vs Symbol subject ([5964](https://bugs.ruby-lang.org/issues/5964), [7792](https://bugs.ruby-lang.org/issues/7792), [14277](https://bugs.ruby-lang.org/issues/14277)) there are some conclusions we can assume:
* Current String vs Symbol is not the ideal scenario. See: Matz and Koichi comments.
* Current philosophy is to use Symbols as identifiers and Strings when strings are needed.
* Current situation is that Symbols are being used in many code bases as strings except for strings that really need the String methods.
* Current situation is that we are designing APIs to handle both String and Symbol inputs forcing an overhead of API development.

I propose the deprecation of `Symbol` class and the introduction of `String#symbol?`.

```ruby
foo = :foo
foo.class # => String
foo.symbol? # => true
bar = "bar"
bar.class # => String
bar.symbol? # => false
```

For backwards compatibility transition path I propose:

```ruby
class Symbol
  def self.===(var)
    warn ("Warning message regarding deprecated class")
    if var.class == Symbol
      true
    elsif var.class == String && var.symbol?
      true
    else
      false
    end
  end
end

class String
  def is_a?(klass)
    case klass
    when String
      true
    when Symbol
      self.symbol?
    else
      false
    end
  end
end
```



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>