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


Since not everyone here knows Sequel, let me give an example on how strings and symbols are treated differently in that library.

DB[:users].select(:name).sql == %q{SELECT "name" FROM "users"}
DB[:users].select('name').sql == %q{SELECT 'name' FROM "users"}

Even though in the query above only the symbol version makes sense, there are many other queries where selecting a string makes sense. For example:

DB[:user_groups].import [:user_id, :group_name], DB[:users].select(:id, 'children').where{ age <= 10 }

I mean, there are legit cases where the distinction between strings and symbols are useful. If symbols didn't exist in the first place, I guess the last import statement would be written like:

DB['user_groups'].import ['user_id', 'group_name'], DB['users'].select('id', Sequel.lit('children')).where{ age <= 10 }

But if we introduce such an incompatible change now, lots of applications and libraries would require significant changes in order to be compatible with the new Ruby release introducing such changes.

I believe 90% of the pain regarding strings and symbols come from them being compared differently, specially when using as hash keys. For example:

my_hash = { a: 1 }
[my_hash[:a], my_hash['a']] == [1, nil]

deserialized_hash = JSON.parse(JSON.unparse my_hash)
# the above would be equivalent to the pseudo code below:
# store_in_redis 'cache_key', my_hash
# cached_hash = restore_from_redis 'cache_key'

[deserialized_hash[:a], deserialized_hash['a']] == [nil, 1]

While there are legit and very common usage for obj.is_a?(Symbol) and Symbol === obj (like in case statements, for example), it's much rarer to find cases where hash[:a] != hash['a'] and both are not nil. And in most of those cases it's actually a software bug, rather than the author's intention.

Maybe if we could change Hash's behavior to compare strings and symbols the same way as keys, most of the pain would have gone without breaking too much code. Also, I'm curious how much code would be broken if Ruby allowed this comparison to be true: ":my_id == 'my_id'". Code checking for obj.class, Symbol === obj (case included) and obj.is_a?(Symbol) wouldn't break. So, I guess the incompatibility would only break a few libraries and applications, but I may be wrong.

----------------------------------------
Feature #14277: Improve strings vs symbols ambiguity
https://bugs.ruby-lang.org/issues/14277#change-69158

* Author: dsferreira (Daniel Ferreira)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
This is the ambiguity:

```ruby
alias_method :foo, :bar
alias_method "foo", "bar"
```

Ruby developers are using strings and symbols interchangeably as if they were the same thing.
This is happening in ruby core, in ruby gems and in ruby applications.

---

This discussion as started 5 years ago in two separate feature requests (both rejected): 
* [5964](https://bugs.ruby-lang.org/issues/5964)
* [7792](https://bugs.ruby-lang.org/issues/7792)

I believe ruby will be much better once the ambiguity between strings and symbols is resolved for good
and ruby 3.0 is a very good opportunity to do so.

From further discussions I got a light of hope that a solution may be accepted if certain conditions are met.
Specifically, a clear transition path that could lead the community towards the break of backwards compatibility.

In the issue [Make symbols and strings the same thing](https://bugs.ruby-lang.org/issues/7792)

ko1 (Koichi Sasada) wrote:

> Please consider transition path for users who are using symbol and string difference like:
> 
> key = ...
> ...
> when key
> case String
> ...
> case Symbol
> ...
> end
> How to find out such programs?
> 

he also wrote:

> If you (or someone) find out any good transition path, we think we can consider again.

Can we discuss here what are the rules that would allow the transition path solution to be accepted?

Also what solutions for the problem are we envisioning?

1. Use current symbols syntax as yet another strings syntax and stop using Symbols?
2. Use current symbols syntax as yet another strings syntax and start use Symbols with a new syntax?
3. Use current symbols syntax as yet another strings syntax and use Symbols purely as a class?

From the challenge presented by Koichi I understand that the transition path to be accepted must allow the current code to raise a warning for the situation where the Symbol is not anymore a Symbol but a String.

Is this assumption correct?

If this is the case then all we need is to make `String::===(foo)` and `Symbol::===(foo)` to raise warnings every time `foo` is a string and it was created using former symbol syntax.

This means the `foo` object needs to contain encapsulated the information of the syntax used to define it.

Any drawbacks?

NOTE: (I'm only considering solutions 2. and 3. for the purpose of this analysis. Meaning Symbol class will still exist.)



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