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


Thanks for the explanation on SmallTalk symbols, Bill and Daniel.

It seems to be that symbols are seldom used in SmallTalk while they are often used in Ruby applications, which might explain why SmallTalk users might not complain that much. If you are kind enough, would you mind answering another question on SmallTalk?

Is it possible to generate a symbol from a string in SmallTalk, such as Ruby's 'string'.to_sym?

Conceptually speaking, I see symbols could be thought of as something like: "MYSYMBOL = Object.new". Of course, they could be made so that they would be cheaper to create and use less memory, and even have a corresponding name for debugging or reporting purposes mostly. But when you allow strings to be converted to symbols, people may (and will) just abuse of symbols and they will be used everywhere. If you create a much easier way to write hashes which favors symbols as keys, then things get even more out of control.

In the early days, when I was learning Ruby, the books I've read would also enforce that symbols should be used when performance was a concern (which I consider a misadvice) while talking about the differences between symbols and strings, and provide some micro-benchmarks, which showed big differences by the way back in the time. As people just love micro-benchmarks and feeling performant, there's a whole lot of people that simply used symbols in their libraries and code for "performance" reasons, ignoring that any performance gains achieved by using symbols would be lost if they had to be always converting between symbols and strings.

I understand and embrace the philosophy that we should have great reasons for introducing backwards compatibility and I do think we have them. Currently Ruby's broken from my point of view. The fact that most code bases are fighting bugs caused by h[:a] being different from h['a'] leads to applications crashing much more often than applications would break if we introduced some incompatibilities. I don't really think this could cause something like Python2/3 or Perl5/6 big divisions.

We have introduced support for frozen strings and it went pretty well. Maybe we could replicate the experiment. I disagree of Jeremy Evans in that we should immediately open new issues for every idea we come up while suggesting ways to improve the situation between symbols and strings. Once one of the ideas seems plausible, it's fine to open a separate issue, but for now, it's just a generic discussion. So, how about using magical comments to change the way symbols are created?

I suggested once that we could add some sort of HashWithIndifferentAccess class (with a shorter name hopefully) and create a special short syntax to declare them in issue #9980. What if we extended that to support some flag and magical comment, like we do for frozen strings? When hashes should be interpreted as with indifferent access by default, then {my: 'hash'} would be interpreted as {my: 'hash'}i, which would be a shorter syntax for HashWithIndiferentAccess.new(my: 'hash').

Since the hash issue is the one holding most of the confusion around the differences between symbols and strings, I'm focusing on it in order to try to minimize the impact of introducing incompatible changes and controlling its scope.

So, if we add a magical comment to our files, during the transition phase, we could have code like this working the way I'd like it to be:

~~~ ruby
# hwia-by-default: true

h = {my: 'hash'}
assert h[:my] == h['my']
~~~

Would something like that be considered for a future version of Ruby, as a transition path? We could even warn that the current hash behavior will be changed and that hwia will be the default in the future, so that people would have time to update their code in case they expect h[:a] to be different from h['a']. Ruby could rename the current implementation to something else, and provide, again, a transition path for existing code bases, by allowing them to revert the behavior for those sources by setting "# hwia-by-default: false".

This might cause some confusion in the initial phase, as we still can't know whether the hash we are getting from external sources are HWIA or legacy hashes, but I think the community could embrace it. If the community doesn't embrace it, we won't see any magical comments such as "# hwia-by-default: true" used in the wide. Otherwise we'll know it's a desired feature. Ruby has introduced refinements as an experimental feature initially, and it ended up merged to core. Maybe we could think about a similar strategy for dealing with hashes.

As for comparing strings and symbols, we might provide another another flag/magical comment to interpret :a == 'a' as true. Or we could unify them in a single flag/magical comment, so that if :a == 'a', then it would make sense that hash[:a] should equal hash['a'].

I understand this proposal is not very complete. It's not meant to be. It's supposed to be a starting point for a discussion around this idea. What do you think?

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

* 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>