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


david_macmahon (David MacMahon) wrote:
>  I still think the fundamental issue is that Sequel is returning something that contains symbols, but JSON.parse(JSON.unparse(x)) will never return anything containing a symbol even if x does.  Because of this the "users" variable is assigned something that contains symbols in one case and something that contains no symbols in all other cases.  IMHO, the example shows not a deficiency in the Ruby language itself but rather a (subtle, easy to fall victim to) coding pitfall of not properly managing/reconciling the incompatible return types from the two libraries.

But don't you agree that we wouldn't have this kind of problem if Symbols behave just like Strings? Or if Symbols didn't exist at all? Or even if hashes always behaved as HWIA? This is what I'm talking about. But the biggest problem is that I can't really see any real advantage on symbols behaving differently than strings, except maybe for internal usage of symbols.

>  > I know the code above could be simplified, but I'm avoid the parse -> unparse operation when it is not required (although it would make the code always work in this case):
>  > 
>  >  users = JSON.parse (cache['users'] ||= JSON.unparse db[:users].select(:id, :name).all)
>  
>  This seems an excellent solution IMHO as it clearly results in "users" being assigned the return value of JSON.parse every time and only results in one extra JSON.parse call only on the first time through.  That seems a pretty small price to pay for reconciling the two libraries' incompatible return return types.

You seem to be underestimating how slow JSON.parse can be on big lists. I've spent a lot of time in the past doing benchmarks for several JSON parsers implementations available for Ruby because most of the time spent on some requests were caused by JSON#unparse. JSON#unparse was the bottleneck of some requests. I don't think JSON#parse would be much faster. An extra parse operation on a big list could easily add 100ms to the request timing. That is why I want to avoid it.

Also, it doesn't happen only the first time but on each request.
----------------------------------------
Feature #7792: Make symbols and strings the same thing
https://bugs.ruby-lang.org/issues/7792#change-36002

Author: rosenfeld (Rodrigo Rosenfeld Rosas)
Status: Rejected
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


Recently I had to replace several of my symbols to plain strings in my project. Here is what happened:

I generated some results with some class that would add items to an array like this:

results << {id: 1, name: 'abc'}

Then I would store such results in cache using Redis, encoded as a JSON string. But then when I restore the data from cache the hash will be {'id' => 1, 'name' => 'abc'}.

This wasn't a problem until recently because I never used the results directly in the same request before and would always use the value stored on Redis and parsed by JSON.

But recently I had to use the values directly in a view. But then I had a problem because I would have to use symbols in the results for the first time and strings the next times when the result was available on cache. I really don't want to care about memory management in Ruby if possible and symbols forces me to abandon the new sexy hash syntax many times. Now I have to write

results << {'id' => 1, 'name' => 'abc}

when I'd prefer to write

results << {id: 1, name: 'abc}

This is not the first time I had a bad user experience due to symbols being different from strings. And I'm not the only one or ActiveSupport Hash#with_indifferent_access wouldn't be so popular and Rails wouldn't use it all the time internally.

It is really bad when you have to constantly check how you store your keys in your hashes. Am I using symbols or strings as keys? If you use the wrong type on plain hashes you can find a bad time debugging your code. Or you could just use Hash#with_indifferent_access everywhere, thus reducing performance (I guess) and it is pretty inconvenient anyway.

Or if you're comparing the keys of your hash in some "each" closure you have to worry about it being a symbol or a string too.

Ruby is told to be programmers' friendly and it usually is. But symbols are certainly a big exception.


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