https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112013-02-06T23:13:53ZRuby Issue Tracking SystemRuby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359042013-02-06T23:13:53Ztrans (Thomas Sawyer)
<ul></ul><p>I'm not sure that's even possible. If String#hash produced the same number as Symbol#hash, then that would do the trick, but that probably lead to some unforeseen breakages.</p>
<p>I do know one related thing, though. I don't like having to do:</p>
<pre><code>if (String === x || Symbol === x)
x.to_s
</code></pre>
<p>When all I really want to do is <code>x.to_str</code>, but handle Symbols too.</p>
<p>Oh, btw, I've suggested that Hash add a <code>convert_key</code> procedure which could be used to normalize keys. Very useful, but would obviously mean a bit of speed hit.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359062013-02-06T23:20:21Zluislavena (Luis Lavena)luislavena@gmail.com
<ul></ul><p>rosenfeld: see <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Make Symbols an Alternate Syntax for Strings (Rejected)" href="https://redmine.ruby-lang.org/issues/5964">#5964</a> for similar discussion.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359072013-02-06T23:22:12Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul></ul><p>Mmm, it sounds too big to me.</p>
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/2385">@rosenfeld (Rodrigo Rosenfeld Rosas)</a> I know your situation. But is it really a right solution for you? How about a hash with indifferent access? Or how about changing {foo:1} to be { 'foo' => 1 }, not { :foo => 1 } ? It seems your frustration can be relaxed in several ways. Letting symbols be strings is not the only one and (seems to be) suboptiomal.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359082013-02-06T23:23:17Zyorickpeterse (Yorick Peterse)yorickpeterse@gmail.com
<ul></ul><p>Symbols and Strings both have different use cases and that's actually a<br>
good thing. If you want to be able to use both Strings and Symbols as<br>
your Hash keys you can use something like Hashie:<br>
<a href="https://github.com/intridea/hashie" class="external">https://github.com/intridea/hashie</a></p>
<p>Yorick</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359122013-02-06T23:29:44Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Although I'd really prefer that symbols and strings were the same there is an alternative that would satisfy me as well:</p>
<p>Make Hash behave as HashWithIndifferentAccess and create a new class StrictHash to keep the behavior of the existent Hash class. That way this would work:</p>
<p>a = {a: 1}; a[:a] == a['a']</p>
<p>Also any stdlib libraries, such as JSON, should use Hash instead of StrictHash on parse.</p>
<p>That way it wouldn't really matter if {foo: 1} maps to {:foo => 1} or {'foo' => 1}. By the way I'm still curious to know if we'll ever be able to use string interpolation in the hash syntax, like {"#{'foo'}": 1}.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359132013-02-06T23:33:08Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/6640">@yorickpeterse (Yorick Peterse)</a>, your suggestion wouldn't work for my case. The hash is created by JSON.parse where I don't control the hash creation. And I don't like the idea of monkey patching core classes either. Specially in fundamental classes like Hash. If I patch it to make it behave like HashWithIndifferentAccess it could break many libraries/frameworks in unexpected ways.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359162013-02-06T23:53:10Zyorickpeterse (Yorick Peterse)yorickpeterse@gmail.com
<ul></ul><p>You don't need to hijack any code for it, you'd just use it as<br>
following:</p>
<pre><code> require 'hashie'
parsed = JSON.parse('{"name": "Ruby"}')
hash = Hashie::Mash.new(parsed)
hash.name # => "Ruby"
hash['name'] # => "Ruby"
hash[:name] # => "Ruby"
</code></pre>
<p>We use Hashie in various production applications and it works quite well<br>
for us.</p>
<p>Yorick</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359192013-02-06T23:53:11Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 06-02-2013 12:36, Yorick Peterse escreveu:</p>
<blockquote>
<p>You don't need to hijack any code for it, you'd just use it as<br>
following:</p>
<pre><code>require 'hashie'
parsed = JSON.parse('{"name": "Ruby"}')
hash = Hashie::Mash.new(parsed)
hash.name # => "Ruby"
hash['name'] # => "Ruby"
hash[:name] # => "Ruby"
</code></pre>
<p>We use Hashie in various production applications and it works quite well<br>
for us.</p>
</blockquote>
<p>So you get a performance hit because you don't want to worry about<br>
symbols while symbols are meant to give you better performance, right?<br>
How ironic is that?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359212013-02-06T23:58:44Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>I'd just like to highlight what performance impact we may be referring to:</p>
<p><a href="https://gist.github.com/rosenfeld/4723061" class="external">https://gist.github.com/rosenfeld/4723061</a></p>
<p>I'll copy it here:</p>
<p>require 'benchmark'</p>
<p>hashes = []<br>
1_000_000.times { hashes << { some_key_name: 1, 'some_key_name' => 2 }}<br>
Benchmark.bmbm do |x|<br>
x.report { hashes.map{|h| h[:some_key_name]} }<br>
x.report { hashes.map{|h| h['some_key_name']} }<br>
end</p>
<p>Result:</p>
<p>ruby symbols-performance.rb<br>
Rehearsal ------------------------------------<br>
0.540000 0.010000 0.550000 ( 0.543421)<br>
0.680000 0.020000 0.700000 ( 0.705931)<br>
--------------------------- total: 1.250000sec</p>
<pre><code> user system total real
</code></pre>
<p>0.240000 0.000000 0.240000 ( 0.244554)<br>
0.380000 0.000000 0.380000 ( 0.391517)</p>
<p>Does this small hit in performance worth all the hassle that it is to have to differentiate symbols from strings?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359252013-02-07T00:29:25Zyorickpeterse (Yorick Peterse)yorickpeterse@gmail.com
<ul></ul><p>I don't think I'm following you, can you explain what's supposedly<br>
ironic about it? Using Hashie only "slows" things down based on whether<br>
you use Symbols, Strings or object attributes. Unless you use it <em>all</em><br>
over the place the performance impact is small.</p>
<p>I personally don't fully agree with what Hashie does because I believe<br>
people should be competent enough to realize that when they take in<br>
external data it's going to be String instances (for keys that is).</p>
<p>Having said that, I think fundamentally changing the way Ruby works when<br>
it comes to handling Strings and Symbols because developers can't be<br>
bothered fixing the root cause of the problem is flawed. If you're<br>
worried about a ddos stop converting everything to Symbols. If you're<br>
worried about not remember what key type to use, use a custom object or<br>
document it so that people can easily know.</p>
<p>While Ruby is all about making the lifes easier I really don't want it<br>
to become a language that spoon feeds programmers because they're too<br>
lazy to type 1 extra character <em>or</em> convert the output manually. Or<br>
better: use a custom object as mention above.</p>
<p>The benchmark you posted is flawed because it does much, much more than<br>
benchmarking the time required to create a new Symbol or String<br>
instance. Lets take a look at the most basic benchmark of these two data<br>
types:</p>
<pre><code> require 'benchmark'
amount = 50000000
Benchmark.bmbm(40) do |run|
run.report 'Symbols' do
amount.times do
:foobar
end
end
run.report 'Strings' do
amount.times do
'foobar'
end
end
end
</code></pre>
<p>On the laptop I'm currently using this results in the following output:</p>
<pre><code> Rehearsal
</code></pre>
<hr>
<pre><code> Symbols 2.310000 0.000000
</code></pre>
<p>2.310000 ( 2.311325)<br>
Strings 5.710000 0.000000<br>
5.710000 ( 5.725365)<br>
-------------------------------------------------------------------<br>
total: 8.020000sec</p>
<pre><code> user system
</code></pre>
<p>total real<br>
Symbols 2.670000 0.000000<br>
2.670000 ( 2.680489)<br>
Strings 6.560000 0.010000<br>
6.570000 ( 6.584651)</p>
<p>This shows that the use of Strings is roughly 2,5 times slower than<br>
Symbols. Now execution time isn't the biggest concern in this case, it's<br>
memory usage. For this I used the following basic benchmark:</p>
<pre><code> def get_memory
return `ps -o rss= #{Process.pid}`.strip.to_f
end
def benchmark_memory
before = get_memory
yield
return get_memory - before
end
amount = 50000000
puts "Start memory: #{get_memory} KB"
symbols = benchmark_memory do
amount.times do
:foobar
end
end
strings = benchmark_memory do
amount.times do
'foobar'
end
end
puts "Symbols used #{symbols} KB"
puts "Strings used #{strings} KB"
</code></pre>
<p>This results in the following:</p>
<pre><code> Start memory: 4876.0 KB
Symbols used 0.0 KB
Strings used 112.0 KB
</code></pre>
<p>Now I wouldn't be too surprised if there's some optimization going on<br>
because I'm re-creating the same values over and over again but it<br>
already shows a big difference between the two.</p>
<p>To cut a long story short: I can understand what you're trying to get<br>
at, both with the two data types being merged and the ddos issue.<br>
However, I feel neither of these issues are an issue directly related to<br>
Ruby itself. If Ruby were to automatically convert things to Symbols for<br>
you then yes, but in this case frameworks such as Rails are the cause of<br>
the problem. Merging the two datatypes would most likely make such a<br>
huge different usage/code wise that it would probably be something for<br>
Ruby 5.0 (in other words, not in the near future).</p>
<p>Yorick</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359352013-02-07T02:23:17Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 06-02-2013 13:25, Yorick Peterse escreveu:</p>
<blockquote>
<p>I don't think I'm following you, can you explain what's supposedly<br>
ironic about it? Using Hashie only "slows" things down based on whether<br>
you use Symbols, Strings or object attributes. Unless you use it <em>all</em><br>
over the place the performance impact is small.</p>
</blockquote>
<p>What I'm trying to say is that the main reason why symbols exist in Ruby<br>
in the first place is performance from what I've been told.</p>
<p>But then people don't want to worry if hashes are indexed by strings or<br>
symbols so they end up using some kind of HashWithIndifferentAccess or<br>
similar techniques. But since the normal Hash class doesn't behave this<br>
way you have to loop through all hashes in an object returned by<br>
JSON.parse to make them behave as HashWithIndifferentAccess, which is<br>
has a huge performance hit when compared to the small gains symbols<br>
could add.</p>
<blockquote>
<p>I personally don't fully agree with what Hashie does because I believe<br>
people should be competent enough to realize that when they take in<br>
external data it's going to be String instances (for keys that is).</p>
</blockquote>
<p>It is not a matter of being competent or not. You can't know in advance<br>
if a hash returned by some external code is indexed by string or<br>
symbols. You have to test by yourself or check the documentation. Or you<br>
could just use a HashWithIndifferentAccess class and stop worrying about<br>
it. This has a big impact on coding speed and software maintenance,<br>
which is the big problem in my opinion.</p>
<blockquote>
<p>Having said that, I think fundamentally changing the way Ruby works when<br>
it comes to handling Strings and Symbols because developers can't be<br>
bothered fixing the root cause of the problem is flawed.</p>
</blockquote>
<p>People reading some Ruby book will notice that it is not particularly<br>
designed with performance in mind but it is designed mostly towards<br>
programmer's happiness. If that is the case, then worrying about<br>
bothered programmers makes sense to a language like Ruby in my opinion.</p>
<blockquote>
<p>If you're worried about a ddos</p>
</blockquote>
<p>DDoS is a separate beast that can't be easily prevented no matter what<br>
language/framework you use. I'm just talking about DoS exploiting<br>
through memory exhaustion due to symbols not being collected. Anyway,<br>
this is a separate issue from this one and would be better discussed in<br>
that separate thread.</p>
<blockquote>
<p>stop converting everything to Symbols.</p>
</blockquote>
<p>I'm not converting anything to symbols. Did you read the feature<br>
description use case? I'm just creating regular hashes using the new<br>
sexy hash syntax which happens to create symbols instead of strings.<br>
Then when I serialize my object to JSON for storing on Redis for caching<br>
purpose I'll get a hash indexed by strings instead of symbols. That<br>
means that when I'm accessing my hash I have to be worried if the hash<br>
has been just generated or if it was loaded from Redis to decide if I<br>
should use strings or symbols to get the hash values. There are many<br>
more similar situations where this difference between symbols and<br>
strings will cause confusion. And I don't see much benefits in keeping<br>
them separate things either.</p>
<blockquote>
<p>If you're worried about not remember what key type to use, use a<br>
custom object or<br>
document it so that people can easily know.</p>
</blockquote>
<p>This isn't possible when you're serializing/deserializing using some<br>
library like JSON or any other. You don't control how hashes are created<br>
by such libraries.</p>
<blockquote>
<p>While Ruby is all about making the lifes easier I really don't want it<br>
to become a language that spoon feeds programmers because they're too<br>
lazy to type 1 extra character <em>or</em> convert the output manually. Or<br>
better: use a custom object as mention above.</p>
</blockquote>
<p>Again, see the ticket description first before assuming things.</p>
<blockquote>
<p>The benchmark you posted is flawed because it does much, much more than<br>
benchmarking the time required to create a new Symbol or String<br>
instance. Lets take a look at the most basic benchmark of these two data<br>
types:</p>
<pre><code>require 'benchmark'
amount = 50000000
Benchmark.bmbm(40) do |run|
run.report 'Symbols' do
amount.times do
:foobar
end
end
run.report 'Strings' do
amount.times do
'foobar'
end
end
end
</code></pre>
<p>On the laptop I'm currently using this results in the following output:</p>
<pre><code>Rehearsal
</code></pre>
<hr>
<pre><code>Symbols 2.310000 0.000000
</code></pre>
<p>2.310000 ( 2.311325)<br>
Strings 5.710000 0.000000<br>
5.710000 ( 5.725365)</p>
<hr>
<p>total: 8.020000sec</p>
<pre><code> user system
</code></pre>
<p>total real<br>
Symbols 2.670000 0.000000<br>
2.670000 ( 2.680489)<br>
Strings 6.560000 0.010000<br>
6.570000 ( 6.584651)</p>
<p>This shows that the use of Strings is roughly 2,5 times slower than<br>
Symbols. Now execution time isn't the biggest concern in this case, it's<br>
memory usage.</p>
</blockquote>
<p>Exactly, no real-world software would consist mostly of creating<br>
strings/symbols. Even in a simplistic context like my example, it is<br>
hard to notice any impact on the overall code caused by string<br>
allocation taking more time than symbols.When we get more complete code<br>
we'll notice that it really doesn't make any difference if we're using<br>
symbols or strings all over our code...</p>
<p>Also, any improvements on threading and parallelizing support are likely<br>
to yield much bigger performance boots than any micro-optimization with<br>
symbols instead of strings.</p>
<blockquote>
<p>For this I used the following basic benchmark:</p>
<pre><code>def get_memory
return `ps -o rss= #{Process.pid}`.strip.to_f
end
def benchmark_memory
before = get_memory
yield
return get_memory - before
end
amount = 50000000
puts "Start memory: #{get_memory} KB"
symbols = benchmark_memory do
amount.times do
:foobar
end
end
strings = benchmark_memory do
amount.times do
'foobar'
end
end
puts "Symbols used #{symbols} KB"
puts "Strings used #{strings} KB"
</code></pre>
<p>This results in the following:</p>
<pre><code>Start memory: 4876.0 KB
Symbols used 0.0 KB
Strings used 112.0 KB
</code></pre>
<p>Now I wouldn't be too surprised if there's some optimization going on<br>
because I'm re-creating the same values over and over again but it<br>
already shows a big difference between the two.</p>
</blockquote>
<p>112KB isn't certainly a big difference in my opinion unless you're<br>
designing some embedded application. I've worked with embedded devices<br>
in the past and although I see some attempts to make a lighter Ruby<br>
subset (like mRuby) for such use-case I'd certainly use C or C++ for my<br>
embedded apps these days. Did you know that Java initially was supposed<br>
to be used by embedded devices from what I've been told? Then it tried<br>
to convince people to use it to create multi-platform desktop apps.<br>
After that its initial footprint was so big that it wasn't a good idea<br>
to try it on embedded devices for most cases. Then they tried to make it<br>
work in browsers through applets. Now it seems people want to use Java<br>
mostly for web servers (HTTP and other protocols). The result was a big<br>
mess in my opinion. I don't think Ruby (the full specification) should<br>
be concerned about embedded devices. C is already a good fit for devices<br>
with small memory constraints. When you consider using Ruby it is likely<br>
that you have more CPU and memory resources than a typical small device<br>
would have, so 112KB wouldn't make much difference.</p>
<p>And for embedded devices, it is also recommended that they run some RTOS<br>
instead of plain Linux. If they want to keep with Linux, an option would<br>
be to patch it with Xenomai patch for instance. But in that case, any<br>
real-time task would be implemented in C, not in Ruby or any other<br>
language subjected to garbage collected, like Java. So, if we keep the<br>
focus on applications running on normal computers, 112KB won't really<br>
make any difference, don't you agree?</p>
<blockquote>
<p>To cut a long story short: I can understand what you're trying to get<br>
at, both with the two data types being merged and the ddos issue.<br>
However, I feel neither of these issues are an issue directly related to<br>
Ruby itself. If Ruby were to automatically convert things to Symbols for<br>
you then yes, but in this case frameworks such as Rails are the cause of<br>
the problem.</p>
</blockquote>
<p>Rails is not related at all to the use case I pointed out in this ticket<br>
description. It happens with regular Ruby classes (JSON, Hash) and with<br>
the "redis" gem that is independent from Rails.</p>
<blockquote>
<p>Merging the two datatypes would most likely make such a<br>
huge different usage/code wise that it would probably be something for<br>
Ruby 5.0 (in other words, not in the near future).</p>
</blockquote>
<p>Ruby 3.0 won't happen in a near future. Next Major means Ruby 3.0 if I<br>
understand it correctly.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359392013-02-07T03:23:17Zyorickpeterse (Yorick Peterse)yorickpeterse@gmail.com
<ul></ul><blockquote>
<p>What I'm trying to say is that the main reason why symbols exist in<br>
Ruby in the first place is performance from what I've been told.</p>
</blockquote>
<p>Correct, and your proposed changes would completely nullify those<br>
performance benefits (see below).</p>
<blockquote>
<p>People reading some Ruby book will notice that it is not particularly<br>
designed with performance in mind but it is designed mostly towards<br>
programmer's happiness. If that is the case, then worrying about<br>
bothered programmers makes sense to a language like Ruby in my<br>
opinion.</p>
</blockquote>
<p>So basically what you're saying is "Ruby is written for happiness and<br>
not performance, lets make it even more slow!". I'd rather see a world<br>
where Ruby is both fast (enough) and easy to use instead of it being<br>
easy to use and slower than a sloth.</p>
<p>Regarding the benchmarking information, you're missing a crucial aspect.<br>
While the numbers in the specific examples I gave both clearly show that<br>
the use of Strings is substantially slower. Yes, it's "only" 112 kb but<br>
the difference will keep growing and growing until you hit your memory<br>
limit.</p>
<p>This is exactly one of the reasons Symbols exist: to make it easier and<br>
faster to use commonly re-used Strings. The best example of this are<br>
Hash keys.</p>
<blockquote>
<p>This isn't possible when you're serializing/deserializing using some<br>
library like JSON or any other. You don't control how hashes are<br>
created by such libraries.</p>
</blockquote>
<p>Of course it is. Marshal allows you to store arbitrary Ruby objects<br>
(with the exception of a few such as Proc instances), in other cases you<br>
can re-create your objects based on the supplied Hash.</p>
<p>If you do not like using raw Hashes the solution in my opinion is not to<br>
more or less re-write Ruby (and break everything that exists in the<br>
process) but instead solve this on your own application level. Using<br>
Hashie is one example but another one, one I consider far better, is to<br>
use your own classes. Consider the following:</p>
<pre><code> hash = {'id' => '123-abc-456', 'body' => 'hello'}
if hash['id'] and !hash['id'].empty?
puts "Processing message ID #{hash['id']}"
end
if hash['body'] and !hash['body'].empty?
do_something(hash['body'])
end
</code></pre>
<p>This is not a flaw in your proposal in particular but it's one of the<br>
reasons why I'm not a big fan of using Hashes all over the place. If in<br>
this example the "id" key is suddenly changed to "ID" you now have at<br>
least 3 places where you have to modify your code and most likely other<br>
places further down the line. This can be solved by doing something as<br>
simple as the following:</p>
<pre><code> class Message
attr_reader :id, :body
def initialize(options)
@id = options['id']
@body = options['body']
end
def has_id?
return @id && !@id.empty?
end
def has_body?
return @body && !@body.empty?
end
end
</code></pre>
<p>This allows you to write the following instead:</p>
<pre><code> message = Message.new({'id' => '123-abc-456', 'body' => 'hello'})
if message.has_id?
puts "Processing message ID #{message.id}"
end
if has_body?
do_something(message.body)
end
</code></pre>
<p>In this specific example it may seem a bit like an overkill but if that<br>
Hash gets used in a dozen places you can save yourself tremendous<br>
amounts of time by just wrapping a class around it.</p>
<p>Yorick</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359402013-02-07T03:53:13Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 06-02-2013 16:22, Yorick Peterse escreveu:</p>
<blockquote>
<blockquote>
<p>What I'm trying to say is that the main reason why symbols exist in<br>
Ruby in the first place is performance from what I've been told.<br>
Correct, and your proposed changes would completely nullify those<br>
performance benefits (see below).</p>
</blockquote>
<blockquote>
<p>People reading some Ruby book will notice that it is not particularly<br>
designed with performance in mind but it is designed mostly towards<br>
programmer's happiness. If that is the case, then worrying about<br>
bothered programmers makes sense to a language like Ruby in my<br>
opinion.<br>
So basically what you're saying is "Ruby is written for happiness and<br>
not performance, lets make it even more slow!". I'd rather see a world<br>
where Ruby is both fast (enough) and easy to use instead of it being<br>
easy to use and slower than a sloth.</p>
</blockquote>
<p>Regarding the benchmarking information, you're missing a crucial aspect.<br>
While the numbers in the specific examples I gave both clearly show that<br>
the use of Strings is substantially slower. Yes, it's "only" 112 kb but<br>
the difference will keep growing and growing until you hit your memory<br>
limit.</p>
</blockquote>
<p>Man, you're instantiating 50 millions strings and it only increased the<br>
memory in 112KB. If your application creates so many strings that won't<br>
be garbage collected then it is unlikely that symbols would help as a<br>
replacement.</p>
<p>And "growing until you hit your memory limit" is actually only valid for<br>
symbols, not for strings that are garbage collected already. Unless you<br>
have some leak in your code that prevent those strings from being<br>
collected by GC.</p>
<blockquote>
<p>This is exactly one of the reasons Symbols exist: to make it easier and<br>
faster to use commonly re-used Strings. The best example of this are<br>
Hash keys.</p>
</blockquote>
<p>Most of the programming languages don't support the concept of symbols<br>
like Ruby. And you won't see C or C++ programmers complaining about this<br>
neither.</p>
<blockquote>
<blockquote>
<p>This isn't possible when you're serializing/deserializing using some<br>
library like JSON or any other. You don't control how hashes are<br>
created by such libraries.<br>
Of course it is. Marshal allows you to store arbitrary Ruby objects<br>
(with the exception of a few such as Proc instances), in other cases you<br>
can re-create your objects based on the supplied Hash.</p>
</blockquote>
</blockquote>
<p>Marshal is not portable across multiple languages (I use both Groovy and<br>
Ruby in my overall application interacting with Redis). I'm talking<br>
about JSON here. You don't have to find an alternative to JSON. Just try<br>
to understand the issue I'm talking about.,</p>
<blockquote>
<p>If you do not like using raw Hashes the solution in my opinion is not to<br>
more or less re-write Ruby (and break everything that exists in the<br>
process)</p>
</blockquote>
<p>Like what?</p>
<blockquote>
<p>but instead solve this on your own application level. Using<br>
Hashie is one example but another one, one I consider far better, is to<br>
use your own classes. Consider the following:</p>
</blockquote>
<p>Ok, I won't repeat myself. Please give an example for the Redis + JSON<br>
serialization use case presented in the ticket description.</p>
<p>Otherwise you cleared missed the point.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359422013-02-07T04:23:16Zyorickpeterse (Yorick Peterse)yorickpeterse@gmail.com
<ul></ul><blockquote>
<p>And "growing until you hit your memory limit" is actually only valid<br>
for symbols, not for strings that are garbage collected already.<br>
Unless you have some leak in your code that prevent those strings from<br>
being collected by GC.</p>
</blockquote>
<p>Since existing code (and developers) assume that Symbols are only<br>
created once they are generally used all over the place without any side<br>
effects. The moment you start garbage collecting them there's an<br>
increased chance of the GC kicking in right in the middle of (say) an<br>
HTTP request. Yes, you may now be able to use both Symbols and Strings<br>
as Hash keys but you now have to deal with increased GC activity.</p>
<p>Note that this of course depends on the code you're using. If you use<br>
carefully written code that doesn't use Symbols this is not going to be<br>
an issue. However, pretty every single Gem out there uses them and a lot<br>
of them also use them quite heavily.</p>
<blockquote>
<p>Most of the programming languages don't support the concept of symbols<br>
like Ruby. And you won't see C or C++ programmers complaining about<br>
this neither</p>
</blockquote>
<p>C has a goto operator, does that mean Ruby should have one too (I'm<br>
aware it's already there, it's not just enabled unless you specify some<br>
compiler flag)? Just because one language has feature X it doesn't mean<br>
all the others should have it too.</p>
<blockquote>
<p>Marshal is not portable across multiple languages (I use both Groovy<br>
and Ruby in my overall application interacting with Redis). I'm<br>
talking about JSON here. You don't have to find an alternative to<br>
JSON. Just try to understand the issue I'm talking about.,</p>
</blockquote>
<p>It wasn't suggested as an alternative, merely an example that there is a<br>
way of serializing arbitrary Ruby data.</p>
<blockquote>
<p>Ok, I won't repeat myself. Please give an example for the Redis +<br>
JSON serialization use case presented in the ticket description.</p>
<p>Otherwise you cleared missed the point.</p>
</blockquote>
<p>Take a closer look at my previous Email, there's a fairly big example at<br>
the bottom of it that you can't really miss. However, just in case:</p>
<pre><code> require 'redis'
require 'json'
client = Redis.new
client.set('user', JSON({'id' => 1, 'name' => 'John Doe'}))
# This would happen somewhere else (e.g. an external process)
hash = JSON(client.get('user'))
user = User.new(hash)
# instead of user['id'] you can now just do `user.id` which means
# that if the key name ever changes you only have to change it in
# one place.
if user.id
# ...
end
</code></pre>
<p>Another benefit is that this lets you attach your own methods to the<br>
object without having to monkeypatch existing classes or using helper<br>
methods (which feels very much like procedural programming).</p>
<p>Yorick</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359452013-02-07T05:19:51Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>=begin<br>
This proposal has no description of how to overlay the functionality of strings (mutable) with symbols (immutable).</p>
<p>This was previously tried during 1.9 which had such a plan but was ultimately rejected.</p>
<p>Due to a previous attempt and failure along with the lack of a concrete plan in this feature request I will reject this.</p>
<p>As to symbols or strings as hash keys, you should almost always use strings. This is the current community best-practice consensus.</p>
<p>You should only use symbols as keys in a Hash if you have a small, fixed set of keys and do not use user input to look up items in the hash.</p>
<p>Converting a string to a symbol you look up in a hash is not recommended. You have created two hash lookups out of one (the first for string to symbol mapping, the second for the lookup in your hash) and you risk a DoS as symbols are not garbage collected.</p>
<p>Consider this benchmark:</p>
<p>require 'benchmark'</p>
<p>N = 10_000_000</p>
<p>Benchmark.bmbm do |bm|<br>
bm.report 'NULL' do<br>
h = { 'foo' => 'bar'}</p>
<pre><code> N.times do
# null
end
end
bm.report 'string key, string lookup' do
h = { 'foo' => 'bar' }
N.times do
h['foo']
end
end
bm.report 'symbol key, symbol lookup' do
h = { :foo => 'bar' }
N.times do
h[:foo]
end
end
bm.report 'symbol key, string intern lookup' do
h = { :foo => 'bar' }
N.times do
h['foo'.intern]
end
end
</code></pre>
<p>end</p>
<p>Here are the results:</p>
<p>Rehearsal --------------------------------------------------------------------<br>
NULL 0.440000 0.000000 0.440000 ( 0.448186)<br>
string key, string lookup 1.870000 0.000000 1.870000 ( 1.866935)<br>
symbol key, symbol lookup 0.660000 0.000000 0.660000 ( 0.661466)<br>
symbol key, string intern lookup 2.230000 0.000000 2.230000 ( 2.222772)<br>
----------------------------------------------------------- total: 5.200000sec</p>
<pre><code> user system total real
</code></pre>
<p>NULL 0.430000 0.000000 0.430000 ( 0.434306)<br>
string key, string lookup 1.860000 0.000000 1.860000 ( 1.862942)<br>
symbol key, symbol lookup 0.680000 0.000000 0.680000 ( 0.681767)<br>
symbol key, string intern lookup 2.270000 0.010000 2.280000 ( 2.264888)</p>
<p>While symbol key and symbol lookup is 2.7 times faster than string key and string lookup, it is also 1.2 times faster than interning a string for a symbol lookup.</p>
<p>=end</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359502013-02-07T08:01:29Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>There's another issue here, which has been overlooked because it's philosophical rather than technical:</p>
<p>symbols aren't strings.</p>
<p>A string's value is a sequence of characters, which can be iterated over and operated on.</p>
<p>A symbol's only value is itself, is used as a token, and only supports comparison and casting operations. In MRI it's actually implemented as an integer, which can be looked up by its name (like a C enum).</p>
<p>I strongly believe there is already too much conflation between the two (completely unrelated) types. We can never benefit by blurring them any further.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359522013-02-07T08:51:38Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/47">@drbrain (Eric Hodel)</a>, that means I'm unable to do things like</p>
<p>results << {id: id, name: name}</p>
<p>and have to use the old syntax all the time (and worrying about the differences all the time):</p>
<p>results << {'id' => id, 'name' => 'name'}</p>
<p>I still believe MRI should try to optimize frozen strings instead of symbols and just make symbols behave like frozen strings. :symbol would be a shortcut to 'symbol'.freeze.</p>
<p>I don't really think any of those micro-benchmarks would justify all the hassle and unhappiness that symbols bring to Ruby programmers.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359532013-02-07T08:53:17Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 06-02-2013 17:12, Yorick Peterse escreveu:</p>
<blockquote>
<blockquote>
<p>And "growing until you hit your memory limit" is actually only valid<br>
for symbols, not for strings that are garbage collected already.<br>
Unless you have some leak in your code that prevent those strings from<br>
being collected by GC.<br>
Since existing code (and developers) assume that Symbols are only<br>
created once they are generally used all over the place without any side<br>
effects. The moment you start garbage collecting them there's an<br>
increased chance of the GC kicking in right in the middle of (say) an<br>
HTTP request. Yes, you may now be able to use both Symbols and Strings<br>
as Hash keys but you now have to deal with increased GC activity.</p>
</blockquote>
</blockquote>
<p>You currently already don't control when GC activity begins, so I don't<br>
understand how this could be considered any disadvantage...</p>
<blockquote>
<p>Note that this of course depends on the code you're using. If you use<br>
carefully written code that doesn't use Symbols this is not going to be<br>
an issue. However, pretty every single Gem out there uses them and a lot<br>
of them also use them quite heavily.</p>
<blockquote>
<p>Most of the programming languages don't support the concept of symbols<br>
like Ruby. And you won't see C or C++ programmers complaining about<br>
this neither<br>
C has a goto operator, does that mean Ruby should have one too (I'm<br>
aware it's already there, it's not just enabled unless you specify some<br>
compiler flag)? Just because one language has feature X it doesn't mean<br>
all the others should have it too.</p>
</blockquote>
</blockquote>
<p>I didn't mean to say that Ruby should take inspiration on other<br>
languages. My only intent was to show that symbols are not really<br>
required. But then I remembered that both C, C++ and Java support<br>
constant strings. In that sense Ruby could just optimize symbols to<br>
behave like frozen strings and try to optimize that just like the other<br>
languages optimize their constants.</p>
<blockquote>
<blockquote>
<p>Marshal is not portable across multiple languages (I use both Groovy<br>
and Ruby in my overall application interacting with Redis). I'm<br>
talking about JSON here. You don't have to find an alternative to<br>
JSON. Just try to understand the issue I'm talking about.,<br>
It wasn't suggested as an alternative, merely an example that there is a<br>
way of serializing arbitrary Ruby data.</p>
</blockquote>
</blockquote>
<p>I know there are marshaling libraries in Ruby. I just don't understand<br>
how that is relevant to this ticket.</p>
<blockquote>
<blockquote>
<p>Ok, I won't repeat myself. Please give an example for the Redis +<br>
JSON serialization use case presented in the ticket description.</p>
<p>Otherwise you cleared missed the point.<br>
Take a closer look at my previous Email, there's a fairly big example at<br>
the bottom of it that you can't really miss.</p>
</blockquote>
</blockquote>
<p>I didn't miss it. I just didn't keep it in the reply because it is not<br>
relevant to my use case.</p>
<blockquote>
<p>However, just in case:</p>
<pre><code> require 'redis'
require 'json'
client = Redis.new
client.set('user', JSON({'id' => 1, 'name' => 'John Doe'}))
# This would happen somewhere else (e.g. an external process)
hash = JSON(client.get('user'))
user = User.new(hash)
# instead of user['id'] you can now just do `user.id` which means
# that if the key name ever changes you only have to change it in
# one place.
if user.id
# ...
end
</code></pre>
</blockquote>
<p>Ok, you missed the point. Let me show you a complete example as I think<br>
it will help you understanding my concerns (I thought I made myself<br>
clear in the ticket description, but I hope this code example will help<br>
you understand what I meant):</p>
<p>require 'redis'<br>
require 'json'<br>
require 'sequel'</p>
<p>cache = Redis.new<br>
users = cache['users'] || begin<br>
db = Sequel.connect('postgres://user:password@localhost/mydb')<br>
cache['users'] = db[:users].select(:id, :name).map{|r| id: r[:id],<br>
name: r[:name]} # or just select(:id, :name).all<br>
end</p>
<p>p users.first[:id]</p>
<p>What will be the output of the code above?</p>
<p>Exactly! It depends! If the results were cached it will print "nil",<br>
otherwise it will print "1" (or whatever the first id is).</p>
<p>This is the problem that symbols cause because they don't behave like<br>
strings.</p>
<p>Best,<br>
Rodrigo.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359542013-02-07T09:59:15Zdavid_macmahon (David MacMahon)davidm@astro.berkeley.edu
<ul></ul><p>Hi, Rodrigo,</p>
<p>FWIW, I sympathize with your symbols-vs-strings as keys frustration, but I think it's not so trivial to have the best of both worlds (flexibility and performance). Here is a simplification of your example:</p>
<p>require 'redis'<br>
cache = Redis.new<br>
value = :value<br>
key = 'key'</p>
<p>v1 = cache[key] || (cache[key] = value)<br>
v2 = cache[key] || (cache[key] = value)</p>
<p>p v1 # :value or "value"<br>
p v2 # always "value"<br>
p cache[key] == value # always false</p>
<p>IMHO, the crux of the problem here is that Redis converts all Symbols to Strings, but assigning "v1 = cache[key] = value" does not store a String in v1 if value is a Symbol. This could be addressed by doing:</p>
<p>v1 = cache[key] || (cache[key] = value; cache[key])</p>
<p>which will store a String in v1 if value is a Symbol even if key does not yet exist in cache. Yes, it is an extra cache fetch.</p>
<p>The same kind of thing happens if value is a Fixnum. Surely you wouldn't want Fixnums and Strings to be the same thing! :-)</p>
<p>Thanks for starting this fascinating thread,<br>
Dave</p>
<p>On Feb 6, 2013, at 3:45 PM, Rodrigo Rosenfeld Rosas wrote:</p>
<blockquote>
<p>Ok, you missed the point. Let me show you a complete example as I think it will help you understanding my concerns (I thought I made myself clear in the ticket description, but I hope this code example will help you understand what I meant):</p>
<p>require 'redis'<br>
require 'json'<br>
require 'sequel'</p>
<p>cache = Redis.new<br>
users = cache['users'] || begin<br>
db = Sequel.connect('postgres://user:password@localhost/mydb')<br>
cache['users'] = db[:users].select(:id, :name).map{|r| id: r[:id], name: r[:name]} # or just select(:id, :name).all<br>
end</p>
<p>p users.first[:id]</p>
<p>What will be the output of the code above?</p>
<p>Exactly! It depends! If the results were cached it will print "nil", otherwise it will print "1" (or whatever the first id is).</p>
<p>This is the problem that symbols cause because they don't behave like strings.</p>
<p>Best,<br>
Rodrigo.</p>
</blockquote> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359572013-02-07T10:18:22Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/47">@drbrain (Eric Hodel)</a>, that means I'm unable to do things like</p>
<p>results << {id: id, name: name}</p>
<p>and have to use the old syntax all the time (and worrying about the differences all the time):</p>
<p>results << {'id' => id, 'name' => 'name'}</p>
</blockquote>
<p>You say "old syntax," maybe you should think of it as the "general syntax." Or, as I think of it, the "real syntax." The new {id: id} syntax is special case sugar for Hashes keyed on Symbols, which we've already determined is not a great thing to be doing in most cases.</p>
<blockquote>
<p>I still believe MRI should try to optimize frozen strings instead of symbols and just make symbols behave like frozen strings. :symbol would be a shortcut to 'symbol'.freeze.</p>
</blockquote>
<p>But symbols <em>aren't</em> strings. You can't do any of the string-specific things on them, except by first casting them to strings. Why create a string, then use it to generate an (unrelated) type of object? Just create the symbol in the first place (as already happens).</p>
<blockquote>
<p>I don't really think any of those micro-benchmarks would justify all the hassle and unhappiness that symbols bring to Ruby programmers.</p>
</blockquote>
<p>A simple solution presents itself: stop using them. Or I should say, stop using them except when you absolutely must.</p>
<p>If we stop thinking of them as special/frozen/whatever strings, and stop using them as "strings with construction optimisation," this whole issue becomes irrelevant. Then we can also stop using the symbol-specific {a: a} syntax, except when it really makes sense. And voila! everything is gravy.</p>
<p>Earlier you also wrote:</p>
<blockquote>
<p>You can't know in advance if a hash returned by some external code is indexed by string or symbols. You have to test by yourself or check the documentation.</p>
</blockquote>
<p>Indeed. Similarly you can't know in advanced if it's keyed on integers, or CustomMagicClass instances. Not a symbol-specific issue. If the library authors cleared up their misconception that symbols are magic strings, you wouldn't have a problem. Solution: work around their shortcomings, or find/write a better library.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359722013-02-07T19:46:04Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>phluid61 (Matthew Kerwin) wrote:</p>
<blockquote>
<p>You say "old syntax," maybe you should think of it as the "general syntax." Or, as I think of it, the "real syntax." The new {id: id} syntax is special case sugar for Hashes keyed on Symbols, which we've already determined is not a great thing to be doing in most cases.</p>
</blockquote>
<p>I agree that a string is what I want in all cases. That is exactly why I don't feel the need for symbols. If symbols are just really required as a fundamental implementation detail of the MRI implementation, then I don't think it is a good reason to justify keeping them in the language level. Just find other ways to optimize methods/etc lookup in the internal MRI code. This should be a separate discussion from the language design itself.</p>
<p>I'd really prefer you to think if symbols are really a good thing to have in the design of the Ruby language if you forget about all performance impacts it might have on the MRI implementation details. Then, still forgetting about performance and internal implementation details, try to reason why :symbol != 'symbol' is useful in Ruby just like a[:a] != a['a']. I've been using Ruby for several years now and I can tell you for sure that people often want them to behave the same and they don't want to worry about performance impact either. People just don't know when to use symbols and strings.</p>
<p>Take the Sequel library for instance.</p>
<p>DB[:user].select(:id, :name).all will return [{id: 1, name: 'Rodrigo'}] as opposed to [{'id' => 1}, {'name' => 'Rodrigo'}]</p>
<p>A similar case happens all around and people simply are confused whether they should be using symbols or strings in their code. This is specially misleading in hashes, specially because it is not uncommon that you can intermix strings and symbols as hash keys causing frequent bugs. It doesn't make sense to argue vs String vs Integer or Symbol vs Integer because this kind of bug doesn't really happen. People don't confuse Integer with Strings or Symbols. They confuse Symbols with Strings only. And each library will use a different criteria to decide if symbols or strings should be used and that forces each programmer to worry about those differences between libraries.</p>
<blockquote>
<blockquote>
<p>I still believe MRI should try to optimize frozen strings instead of symbols and just make symbols behave like frozen strings. :symbol would be a shortcut to 'symbol'.freeze.</p>
</blockquote>
<p>But symbols <em>aren't</em> strings.</p>
</blockquote>
<p>I know they aren't. That is why I'm asking to change this behavior!</p>
<blockquote>
<p>You can't do any of the string-specific things on them, except by first casting them to strings.</p>
</blockquote>
<p>We all know how symbols are different from strings, it doesn't help repeating it all the way. I'd prefer that you focus on explaining why you think keeping symbols a separate beast is of any usefulness (ignore any performance concerns for now, I'd like to make sure performance is the only factor involved here first).</p>
<blockquote>
<p>Why create a string, then use it to generate an (unrelated) type of object? Just create the symbol in the first place (as already happens).</p>
</blockquote>
<p>This is what I do but I don't control other libraries. Anyway this makes the new sexy hash syntax almost unuseful to me since strings is what I want most of the times. And I really do hate the general syntax for hashes. The new one is more compact and takes me much less type to type and it is also similar to what most languages do (JavaScript, Groovy, etc). The difference is that in the other languages a string is used since they don't have the symbols concept.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359732013-02-07T19:50:26Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Also, so that you stop arguing that the differences between symbols and strings are just like the differences between strings and integers (non-sense), notice that HashWithIndifferentAccess makes this distinction:</p>
<p>h = HashWithIndifferentAccess.new({1 => 'a', a: 'a'})<br>
h['1'] == nil<br>
h[1] == 'a'<br>
h['a'] == 'a'<br>
h[:a] == 'a'</p>
<p>Since you don't see any popular hash implementation that will consider h[1] == h['1'] (like JavaScript), you could take the conclusion that people only really care that string behave differently than symbols.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359742013-02-07T19:59:50Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p>cache = Redis.new<br>
users = cache['users'] || begin<br>
db = Sequel.connect('postgres://user:password@localhost/mydb')<br>
cache['users'] = db[:users].select(:id, :name).map{|r| id: r[:id],<br>
name: r[:name]} # or just select(:id, :name).all</p>
</blockquote>
<p>Sorry, I forgot the JSON conversion in the example above:</p>
<p>cache = Redis.new<br>
db = Sequel.connect('postgres://user:password@localhost/mydb')<br>
users = if cached = cache['users']<br>
JSON.parse cached<br>
else<br>
db[:users].select(:id, :name).all.tap{|u| cache['users'] = JSON.unparse u}<br>
end</p>
<p>I know the code above could be simplified, but I'm avoiding the parse -> unparse operation when it is not required (although it would make the code always work in this case):</p>
<p>users = JSON.parse (cache['users'] ||= JSON.unparse db[:users].select(:id, :name).all)</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359752013-02-07T20:05:39Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>david_macmahon (David MacMahon) wrote:</p>
<blockquote>
<p>Hi, Rodrigo,</p>
<p>FWIW, I sympathize with your symbols-vs-strings as keys frustration, but I think it's not so trivial to have the best of both worlds (flexibility and performance).</p>
</blockquote>
<p>I'm not asking for performance nor flexibility. The only reason I didn't suggest to simply remove symbols at all is because I know it would be promptly rejected since all Ruby code would have to be changed to accomplish a change like that. And I don't really believe that symbols help the overall performance of any Ruby program. I feel it is more likely to reduce performance because people are often using conversions between symbols and strings making the overall performance slower, not faster.</p>
<blockquote>
<p>...<br>
IMHO, the crux of the problem here is that Redis converts all Symbols to Strings...</p>
</blockquote>
<p>Sorry, my example was wrong, I forgot about the JSON serialization. I don't really know what the Redis library does if I try to store a non-string object so I never tried to do so. I'm trying to avoid an unnecessary JSON.parse operation when I don't need it. See my comments above.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359792013-02-07T21:23:11Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>On 7 February 2013 20:46, rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p>I agree that a string is what I want in all cases. That is exactly why I<br>
don't feel the need for symbols. If symbols are just really required as<br>
a fundamental implementation detail of the MRI implementation, then I<br>
don't think it is a good reason to justify keeping them in the language<br>
level. Just find other ways to optimize methods/etc lookup in the<br>
internal MRI code. This should be a separate discussion from the language<br>
design itself.</p>
<p>I'd really prefer you to think if symbols are really a good thing to<br>
have in the design of the Ruby language if you forget about all<br>
performance impacts it might have on the MRI implementation details.</p>
</blockquote>
<p>Ok, methods. They have a bucket of queriable information (a Method<br>
instance), and they have a symbolic representation (a Symbol). I don't<br>
want to have to instantiate an entire Method object (or a whole bunch of<br>
them) every time I want to talk to an object abouts its methods; I just<br>
want a single, simple, universal token that represents that (or those)<br>
method(s).</p>
<p>Sorry, that's a performance optimisation detail. Ok, I don't want to have<br>
to instantiate a Method object that potentially doesn't have a<br>
corresponding method. That could be confusing.</p>
<p>You will now argue that I could as easily use a String as a Symbol, and<br>
yes, ignoring performance and implementation details that is true. But I<br>
don't want to write code that performs poorly. If, in thise case, exposing<br>
implementation details make my code easier and better, then by the gods,<br>
let me use it. It is then up to me not to misuse it. Similarly: why have<br>
any numeric class that isn't Rational?</p>
<p>And for the record: "I don't ever want to use ClassX so let's remove it"<br>
is, frankly, silly.</p>
<blockquote>
<p>Then, still forgetting about performance and internal implementation<br>
details, try to reason why :symbol != 'symbol' is useful in Ruby just<br>
like a[:a] != a['a']. I've been using Ruby for several years now and I<br>
can tell you for sure that people often want them to behave the same and<br>
they don't want to worry about performance impact either.</p>
</blockquote>
<p>Ok, completely philosphically, without any reference to performance or<br>
implementation details, why is a Java enum not equivalent to (or auto-cast<br>
to and from) a Java string? An enum is just a token, yes? It looks like a<br>
string; it often spells a word that people might like to read, even<br>
capitalise. But it's not a string. It's something else. A Symbol is<br>
exactly like that enum.</p>
<p>I, too, have been using Ruby for several years now; and I, too, have seen a<br>
lot of people wanting Symbol and String to behave the same. Hells, at<br>
times even I have wanted that. But the simple fact is: those people<br>
(myself included) are wrong. If they want a String, use a String. If they<br>
want to force a Symbol-shaped peg into a String-shaped hole, then they'll<br>
have to do whatever hoop-jumping is required; exactly as if you want a Java<br>
enum to support implicit coercion to and from a string.</p>
<blockquote>
<p>People just don't know when to use symbols and strings.</p>
</blockquote>
<p>Bingo. Your solution is: hide Symbols from those people. My solution is:<br>
don't change anything; maybe eventually enough people will learn that the<br>
two classes are, in fact, different.</p>
<blockquote>
<p>Take the Sequel library for instance.</p>
</blockquote>
<p>No thanks, apparently the authors don't know the difference between Symbols<br>
and Strings.</p>
<blockquote>
<p>We all know how symbols are different from strings,</p>
</blockquote>
<p>Well apparently not, otherwise this would be a non-issue.</p>
<blockquote>
<p>it doesn't help repeating it all the way.</p>
</blockquote>
<p>Perhaps I believe that if I say it enough times, in enough places, people<br>
might actually notice. And maybe even listen.</p>
<blockquote>
<p>I'd prefer that you focus on explaining why you think keeping symbols a<br>
separate beast is of any usefulness</p>
</blockquote>
<p>I'll choose to interpret that as "... why I think keeping symbols at all<br>
...". Simply: because they're already here. Relegating them to an<br>
implementation detail and hiding them from the language will only break<br>
100% of existing code. Some of that code is good code. Is it worth<br>
breaking everything so a bunch of people can't accidentally use ClassX when<br>
they should be using ClassY?</p>
<p>-- I'll inject this later comment here, because it's topical:</p>
<blockquote>
<p>Also, so that you stop arguing that the differences between symbols and<br>
strings are just like the differences between strings and integers<br>
(non-sense), notice that HashWithIndifferentAccess makes this distinction:<br>
[...]<br>
Since you don't see any popular hash implementation that will consider<br>
h[1] == h['1'] (like JavaScript), you could take the conclusion that<br>
people only really care that string behave differently than symbols.</p>
</blockquote>
<p>Yes, but those are people who don't know the difference between Symbols and<br>
Strings. Just because they don't know it, doesn't make it untrue.<br>
Personally I've never used HashWithIndifferentAccess, or needed to.</p>
<h2>Incidentally those people don't want a Hash at all. They want an<br>
associative array, one that uses something like <=> or === to compare keys<br>
(instead of #hash and #eql?). If RBTree was more mature,<br>
HashWithIndifferentAccess wouldn't be needed. Shall we repeat this<br>
discussion, but this time about Hash and assoc.array instead of Symbol and<br>
String?</h2>
<blockquote>
<p>This is what I do but I don't control other libraries.</p>
</blockquote>
<p>This is true of <em>any</em> issue in a library. If you think the library's<br>
benefits outweigh its costs, then you use the library. If the fact that<br>
the authors erroneously conflate Symbols and Strings is outweighed by the<br>
fact that it's otherwise extremely useful, it's up to you to work around<br>
the shortcomings. Just like if some otherwise brilliant library uses 0<br>
instead of nil, or something.</p>
<blockquote>
<p>Anyway this makes the new sexy hash syntax almost unuseful to me since<br>
strings is what I want most of the times.</p>
</blockquote>
<p>So, like I said before, just don't use it.</p>
<blockquote>
<p>And I really do hate the general syntax for hashes. The new one is more<br>
compact and takes me much less type to type and it is also similar to<br>
what most languages do (JavaScript, Groovy, etc).</p>
</blockquote>
<p>The general syntax served us well enough through 1.8 and 1.9. Personally I<br>
preferred being able to use <code>:</code> at the end of if/when/etc. statements. If<br>
I want to use javascript syntax, there's always node.js</p>
<blockquote>
<p>The difference is that in the other languages a string is used since<br>
they don't have the symbols concept.</p>
</blockquote>
<p>That's a good point. I'd love to be able to change the new syntax so {a:1}<br>
meant {'a'=>1}, but that's not going to happen. As such, in your eyes and<br>
mine, the new syntax is useless for most intents and purposes, so we might<br>
as well keep on writing Ruby code the way we always have (with <code>=></code> tokens).</p>
<p>P.S. sorry to anyone else who is sick of this conversation, but I think it<br>
needs to be had. Let us know if we should take it offline somewhere.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=359822013-02-07T22:23:17Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 07-02-2013 10:04, Matthew Kerwin escreveu:</p>
<blockquote>
<p>On 7 February 2013 20:46, rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p>I agree that a string is what I want in all cases. That is exactly why I<br>
don't feel the need for symbols. If symbols are just really required as<br>
a fundamental implementation detail of the MRI implementation, then I<br>
don't think it is a good reason to justify keeping them in the language<br>
level. Just find other ways to optimize methods/etc lookup in the<br>
internal MRI code. This should be a separate discussion from the<br>
language<br>
design itself.</p>
<p>I'd really prefer you to think if symbols are really a good thing to<br>
have in the design of the Ruby language if you forget about all<br>
performance impacts it might have on the MRI implementation details.</p>
</blockquote>
<p>Ok, methods. They have a bucket of queriable information (a Method<br>
instance), and they have a symbolic representation (a Symbol). I<br>
don't want to have to instantiate an entire Method object (or a whole<br>
bunch of them) every time I want to talk to an object abouts its<br>
methods; I just want a single, simple, universal token that represents<br>
that (or those) method(s).</p>
</blockquote>
<p>Like a string?</p>
<blockquote>
<p>Sorry, that's a performance optimisation detail.</p>
</blockquote>
<p>Before I continue with my arguments and could focus solely on the<br>
performance issue I'd like to confirm that there is no other reason why<br>
symbols do exist. If performance is the sole reason and if I can make<br>
the point that symbols actually degrades most Ruby programs rather than<br>
improve the overall performance then I can still maintain my hopes for<br>
this ticket.</p>
<blockquote>
<p>...<br>
And for the record: "I don't ever want to use ClassX so let's remove<br>
it" is, frankly, silly.</p>
</blockquote>
<p>This is clearly not the reason here. That's why I'm asking: what Symbols<br>
are useful for? Is it performance the only reason why symbols exist?</p>
<p>Symbols cause lots of confusion as I showed in previous examples. That's<br>
why I want to remove it, but I didn't ask to remove it in this ticket<br>
anyway. Just to make it behave exactly like strings.</p>
<blockquote>
<p>...Ok, completely philosphically, without any reference to performance<br>
or implementation details, why is a Java enum not equivalent to (or<br>
auto-cast to and from) a Java string?</p>
</blockquote>
<p>Java, C and C++ have different goals then Ruby. They aim at the best<br>
possible performance given their constraints. They are also statically<br>
typed. Enums have two goals in such languages. Improving performance and<br>
reducing memory footprint is one of them. The other one is to help the<br>
compiler to find errors at compile time by restricting the input type in<br>
some functions/methods and variables. I don't really understand how this<br>
is relevant to this discussion.</p>
<blockquote>
<p>I, too, have been using Ruby for several years now; and I, too, have<br>
seen a lot of people wanting Symbol and String to behave the same.<br>
Hells, at times even I have wanted that. But the simple fact is:<br>
those people (myself included) are wrong. If they want a String, use<br>
a String. If they want to force a Symbol-shaped peg into a<br>
String-shaped hole, then they'll have to do whatever hoop-jumping is<br>
required; exactly as if you want a Java enum to support implicit<br>
coercion to and from a string.</p>
</blockquote>
<p>I don't want that for Java enums and I don't really understand how Java<br>
enums relate to the string vs symbols debate in Ruby.</p>
<blockquote>
<blockquote>
<p>People just don't know when to use symbols and strings.</p>
</blockquote>
<p>Bingo. Your solution is: hide Symbols from those people.</p>
</blockquote>
<p>Yes!</p>
<blockquote>
<p>My solution is: don't change anything; maybe eventually enough people<br>
will learn that the two classes are, in fact, different.</p>
</blockquote>
<p>They won't.</p>
<blockquote>
<blockquote>
<p>Take the Sequel library for instance.</p>
</blockquote>
<p>No thanks, apparently the authors don't know the difference between<br>
Symbols and Strings.</p>
</blockquote>
<p>But I really love the library. Should I really stop using it just<br>
because it returns an array of hashes indexed by symbols? And Sequel is<br>
not the only library doing so. Should I stop using all gems out there<br>
because the authors don't understand they should be always using strings<br>
instead of symbols in such cases?</p>
<p>You should ask yourself: why are authors so confusing about whether to<br>
use strings or symbols? Are they all just stupid? Isn't it clear in all<br>
Ruby books? No, it isn't! It is just really confusing. I'm yet to read<br>
some book that does a strong argument whether you should be using<br>
symbols or strings. They just say that symbols perform better than<br>
strings so authors think: "hey, then I'll just use symbols everywhere<br>
and my gems will perform the best possible way!". But this thinking is<br>
plain wrong because you'll need extra steps for conversions among those<br>
types very often. The fact is that most authors don't really care about<br>
symbols or strings at all. They don't spend their time thinking about<br>
whether they should be using symbols or strings. They don't WANT to<br>
worry about it! And they're not wrong! Since they don't want someone<br>
looking at their code and telling them that their gem could perform<br>
better if they used symbols instead of strings they will just use<br>
symbols everywhere! This reality won't change. That is why I think<br>
programmers shouldn't have to worry about any performance difference<br>
that might exist between using symbols or strings in their code.</p>
<p>If there is a real boost using symbols internally in MRI then this<br>
should be an implementation detail only, not exposed to Ruby programs.<br>
That is why I suggested the optimizations to care if the string is<br>
frozen or not (like other compilers will optimize constants) instead of<br>
creating a new concept (symbols) just for that. They could keep the<br>
:symbol syntax as an alias to 'symbol'.freeze.</p>
<blockquote>
<p>...</p>
<blockquote>
<p>I'd prefer that you focus on explaining why you think keeping symbols a<br>
separate beast is of any usefulness</p>
</blockquote>
<p>I'll choose to interpret that as "... why I think keeping symbols at<br>
all ...". Simply: because they're already here.</p>
</blockquote>
<p>This is not a good argument in my opinion. If you want to keep the<br>
syntax :name as an alias to 'name'.freeze I believe most current Ruby<br>
programs wouldn't be affected by such change.</p>
<blockquote>
<p>... Personally I've never used HashWithIndifferentAccess, or needed to.</p>
</blockquote>
<p>Me neither. But for different reasons. I need the behavior but I don't<br>
think it worths the extra dependencies in my code (ActiveSupport) nor<br>
the cumbersome of writing such a big class name everytime I want my hash<br>
to behave like HWIA. I prefer to take some time to investigate if all my<br>
hash keys are really strings than to just instantiate HWIA all over the<br>
places.</p>
<blockquote>
<p>Incidentally those people don't want a Hash at all. They want an<br>
associative array, one that uses something like <=> or === to compare<br>
keys (instead of #hash and #eql?).</p>
</blockquote>
<p>:a === 'a' is not true so I don't understand how such suggested<br>
associative array would help here.</p>
<blockquote>
<p>...<br>
This is true of <em>any</em> issue in a library. If you think the library's<br>
benefits outweigh its costs, then you use the library. If the fact<br>
that the authors erroneously conflate Symbols and Strings is<br>
outweighed by the fact that it's otherwise extremely useful, it's up<br>
to you to work around the shortcomings. Just like if some otherwise<br>
brilliant library uses 0 instead of nil, or something.</p>
</blockquote>
<p>Again, please don't pretend that the confusion between strings and<br>
symbols are similar to confusions between 0 and nil.</p>
<blockquote>
<p>The general syntax served us well enough through 1.8 and 1.9.</p>
</blockquote>
<p>Actually I never liked writing hashes as {key => value} in all years<br>
I've been working with Ruby. But I won't stop using Ruby just because I<br>
don't like its hash declaration syntax just the way I won't replace<br>
Sequel just because they return hashes indexed by symbols instead of<br>
strings.</p>
<blockquote>
<p>...</p>
<blockquote>
<p>The difference is that in the other languages a string is used since<br>
they don't have the symbols concept.</p>
</blockquote>
<p>That's a good point. I'd love to be able to change the new syntax so<br>
{a:1} meant {'a'=>1}, but that's not going to happen.</p>
</blockquote>
<p>I agree it is unlike to happen. What about another syntax: {{a: 1}} =><br>
{'a' => 1}? Maybe it would worth trying to ask for some syntax change<br>
like this one. We could even add interpolation to it: {{"value<br>
#{computed}": 1}}.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360002013-02-08T02:01:01Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>phluid61 (Matthew Kerwin) wrote:</p>
<blockquote>
<blockquote>
<p>Take the Sequel library for instance.</p>
</blockquote>
<p>No thanks, apparently the authors don't know the difference between Symbols<br>
and Strings.</p>
</blockquote>
<p>Sequel uses symbol keys instead of string keys intentionally. Sequel maps SQL features directly to ruby objects, mapping SQL identifiers (columns/tables/aliases) to ruby symbols and SQL strings to ruby strings. SQL query results can be thought of as a mapping of SQL identifiers to the values for each identifier in the query, thus Sequel uses a hash with symbol keys.</p>
<p>Ruby uses symbols in a very similar way to how SQL uses identifiers, with symbols basically acting as an identifier. The fact that ruby uses symbols as identifiers should be obvious to anyone who has looked at MRI's implementation, where a symbol is simply an alternate representation of an ID (the internal identifier type that MRI uses to map names to values):</p>
<p>#define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)<br>
#define SYM2ID(x) RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT)</p>
<p>The basic philosophical difference between a symbol and a string is a ruby symbol is an identifier, while a ruby string just represents arbitrary data. You should convert a string to a symbol if you know that the data the string contains represents an identifier you would like to use. You should convert a symbol to a string if you are using name of the identifier as data.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360012013-02-08T02:53:15Zdavid_macmahon (David MacMahon)davidm@astro.berkeley.edu
<ul></ul><p>On Feb 7, 2013, at 3:00 AM, rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Make symbols and strings the same thing (Rejected)" href="https://redmine.ruby-lang.org/issues/7792">#7792</a> has been updated by rosenfeld (Rodrigo Rosenfeld Rosas).</p>
<p>rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p>cache = Redis.new<br>
users = cache['users'] || begin<br>
db = Sequel.connect('postgres://user:password@localhost/mydb')<br>
cache['users'] = db[:users].select(:id, :name).map{|r| id: r[:id],<br>
name: r[:name]} # or just select(:id, :name).all</p>
</blockquote>
<p>Sorry, I forgot the JSON conversion in the example above:</p>
<p>cache = Redis.new<br>
db = Sequel.connect('postgres://user:password@localhost/mydb')<br>
users = if cached = cache['users']<br>
JSON.parse cached<br>
else<br>
db[:users].select(:id, :name).all.tap{|u| cache['users'] = JSON.unparse u}<br>
end</p>
</blockquote>
<p>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.</p>
<blockquote>
<p>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):</p>
<p>users = JSON.parse (cache['users'] ||= JSON.unparse db[:users].select(:id, :name).all)</p>
</blockquote>
<p>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.</p>
<p>Dave</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360022013-02-08T03:23:09Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>david_macmahon (David MacMahon) wrote:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>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.</p>
<blockquote>
<blockquote>
<p>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):</p>
<p>users = JSON.parse (cache['users'] ||= JSON.unparse db[:users].select(:id, :name).all)</p>
</blockquote>
<p>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.</p>
</blockquote>
<p>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.</p>
<p>Also, it doesn't happen only the first time but on each request.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360042013-02-08T03:53:17Zdavid_macmahon (David MacMahon)davidm@astro.berkeley.edu
<ul></ul><p>On Feb 7, 2013, at 10:23 AM, rosenfeld (Rodrigo Rosenfeld Rosas) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Make symbols and strings the same thing (Rejected)" href="https://redmine.ruby-lang.org/issues/7792">#7792</a> has been updated by rosenfeld (Rodrigo Rosenfeld Rosas).</p>
<p>david_macmahon (David MacMahon) wrote:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>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?</p>
</blockquote>
<p>Yes, I agree that we wouldn't have this kind of problem if any of those alternatives existed. I'm just not (yet) convinced that any of those alternatives are desirable just to avoid this kind of problem. I do somewhat like the idea of having Hash behave as HWIA. I think the number of real world uses of something like:</p>
<p>{:a => 0, 'a' => 1}</p>
<p>is likely to be very small.</p>
<blockquote>
<blockquote>
<blockquote>
<p>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):</p>
<p>users = JSON.parse (cache['users'] ||= JSON.unparse db[:users].select(:id, :name).all)</p>
</blockquote>
<p>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.</p>
</blockquote>
<p>An extra parse operation on a big list could easily add 100ms to the request timing.</p>
</blockquote>
<p>So use explicit initialization instead of lazy initialization.</p>
<blockquote>
<p>Also, it doesn't happen only the first time but on each request.</p>
</blockquote>
<p>In the original example, JSON.parse was used on every call except the first one. The modified example uses JSON.parse on every call including the first one. That's why I said the modified example has only one extra JSON.parse call (i.e. the one extra one on the first call). If that's too much overhead, either don't use lazy initialization or explicitly invoke the method once at startup to force lazy initialization so it doesn't impact the (un?)lucky first user.</p>
<p>Dave</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360052013-02-08T03:58:06Ztrans (Thomas Sawyer)
<ul></ul><p>I think the best thing to do about this is simply to ask that a HWIA class be added to Ruby's core. That's as far as this issue can possibly go at this time. And be very happy if it happens b/c 1) its hard to get such things to happen and 2) it's a nice big leap in the right direction. Asking for Hash to become a HWIA, is simply asking for too much backward compatibility breakage for a non-sufficient reason. Keeping on about it will do no good and simply fall on deaf ears, and rather then encourage the inclusion of a HWIA, may well do the opposite.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360062013-02-08T04:23:10Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 07-02-2013 16:43, David MacMahon escreveu:</p>
<blockquote>
<blockquote>
<p>...An extra parse operation on a big list could easily add 100ms to the request timing.<br>
So use explicit initialization instead of lazy initialization.</p>
</blockquote>
</blockquote>
<p>Sorry, didn't get. Could you please show some sample code?</p>
<blockquote>
<blockquote>
<p>Also, it doesn't happen only the first time but on each request.<br>
In the original example, JSON.parse was used on every call except the first one. The modified example uses JSON.parse on every call including the first one. That's why I said the modified example has only one extra JSON.parse call (i.e. the one extra one on the first call). If that's too much overhead, either don't use lazy initialization or explicitly invoke the method once at startup to force lazy initialization so it doesn't impact the (un?)lucky first user.</p>
</blockquote>
</blockquote>
<p>I see the confusion. I simplified the code in that example. Here is how<br>
it would look in a real Rails controller:</p>
<p>class MyController</p>
<pre><code>def my_action
@users = if cached = CacheStore.fetch('users')
JSON.parse cached
else
DB[:users].select(:id, :name).all.tap{|u| CacheStore.store
</code></pre>
<p>'users', JSON.unparse u}<br>
end<br>
end<br>
end</p>
<p>Of course I don't cache the users list, this is just a small example.<br>
The real query is much more complex and could take up to a second when<br>
lots (20) of fields are searched using the user interface. Usually the<br>
query would take about 100ms or less (up to 5 fields usually) but then<br>
the user may want to print the results or export to Excel or changing to<br>
another page and caching would help a lot in that case.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360072013-02-08T04:28:36Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Thomas, if you think we could get some constructor for HWIA, like say, {{a: 'a'}}, then it would already help a lot. But I don't see typing such a long name (HashWithIndifferentAccess) whenever I need such behavior being it included on core or not.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360082013-02-08T04:29:28Zdavid_macmahon (David MacMahon)davidm@astro.berkeley.edu
<ul></ul><p>On Feb 7, 2013, at 11:04 AM, Rodrigo Rosenfeld Rosas wrote:</p>
<blockquote>
<p>Em 07-02-2013 16:43, David MacMahon escreveu:</p>
<blockquote>
<blockquote>
<p>...An extra parse operation on a big list could easily add 100ms to the request timing.<br>
So use explicit initialization instead of lazy initialization.</p>
</blockquote>
</blockquote>
<p>Sorry, didn't get. Could you please show some sample code?</p>
</blockquote>
<p>I was referring to the example, but now I see that the real-world variation is not simply lazy initialization, but rather caching of a result derived from user input that may or may not be used again. In the latter case, the result cannot be pre-initialized and an extra JSON.parse would be significant.</p>
<p>Sorry for veering off topic,<br>
Dave</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360092013-02-08T04:55:27Ztrans (Thomas Sawyer)
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/2385">@rosenfeld (Rodrigo Rosenfeld Rosas)</a> Well I would hope for a much shorter name myself. e.g. <code>Map</code>, <code>Index</code>, <code>Dict</code> are some viable candidates.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360112013-02-08T05:08:26Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>I could see myself using "Map(a: 1, b: 2)" instead of "{a: 1, b: 2}" when I want HWIA. Sounds good to you? Should I create a ticket like this one?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360122013-02-08T06:23:17Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>On 7 February 2013 23:09, Rodrigo Rosenfeld Rosas wrote:</p>
<blockquote>
<p>Enums have two goals in such languages. Improving performance and<br>
reducing memory footprint is one of them. The other one is to help the<br>
compiler to find errors at compile time by restricting the input type in<br>
some functions/methods and variables. I don't really understand how this<br>
is relevant to this discussion.</p>
</blockquote>
<p>No, no no no. Enums exist because they are identifiers. They are symbolic<br>
representations of a concept that either does not necessarily otherwise<br>
exist in the code, or does not have to be fully instantiated in order to<br>
discuss it. That is exactly what Symbols are.</p>
<blockquote>
<p>They don't spend their time thinking about whether they should be using<br>
symbols or strings. They don't WANT to worry about it!</p>
</blockquote>
<p>Your overarching goal is to coddle developers who write code without<br>
understanding either the language, or the concepts behind their own code.<br>
There is a massive philosophical disjunct here between you and I, and I<br>
think it will never be overcome.</p>
<blockquote>
<p>I agree it is unlike to happen. What about another syntax: {{a: 1}} =><br>
{'a' => 1}? Maybe it would worth trying to ask for some syntax change<br>
like this one. We could even add interpolation to it:<br>
{{"value #{computed}": 1}}.</p>
</blockquote>
<p>You'd probably be more likely to succeed with a new %string-style notation,<br>
like %h{a:1, b:2}. Although then again, possibly not.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360132013-02-08T06:23:17Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>On 8 February 2013 03:01, jeremyevans0 (Jeremy Evans) <<br>
<a href="mailto:merch-redmine@jeremyevans.net" class="email">merch-redmine@jeremyevans.net</a>> wrote:</p>
<blockquote>
<p>phluid61 (Matthew Kerwin) wrote:</p>
<blockquote>
<blockquote>
<p>Take the Sequel library for instance.</p>
</blockquote>
<p>No thanks, apparently the authors don't know the difference between<br>
Symbols<br>
and Strings.</p>
</blockquote>
<p>Sequel uses symbol keys instead of string keys intentionally. Sequel maps<br>
SQL features directly to ruby objects, mapping SQL identifiers<br>
(columns/tables/aliases) to ruby symbols and SQL strings to ruby strings.<br>
SQL query results can be thought of as a mapping of SQL identifiers to the<br>
values for each identifier in the query, thus Sequel uses a hash with<br>
symbol keys.</p>
</blockquote>
<p>Sorry, I was being glib.</p>
<p>Interestingly, this is actually an example of Symbols being used correctly<br>
(or at least, not just out-right incorrectly). It's a pity people see this<br>
is a problem to be worked around, rather than a feature.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360152013-02-08T07:23:15Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 07-02-2013 19:11, Matthew Kerwin escreveu:</p>
<blockquote>
<p>On 7 February 2013 23:09, Rodrigo Rosenfeld Rosas wrote:</p>
<blockquote>
<p>Enums have two goals in such languages. Improving performance and<br>
reducing memory footprint is one of them. The other one is to help the<br>
compiler to find errors at compile time by restricting the input type in<br>
some functions/methods and variables. I don't really understand how this<br>
is relevant to this discussion.</p>
</blockquote>
<p>No, no no no. Enums exist because they are identifiers. They are<br>
symbolic representations of a concept that either does not necessarily<br>
otherwise exist in the code, or does not have to be fully instantiated<br>
in order to discuss it. That is exactly what Symbols are.</p>
</blockquote>
<p>If you really believe symbols are similar to enums I guess you haven't<br>
done much C, C++ or Java programming and used enums. Here is the main<br>
reason why enums exist. First let me notice that C and Java implement<br>
enums in different ways:</p>
<p>C example:</p>
<p>typedef enum {HEAD, TAIL} coin_side;<br>
coin_side my_coin = HEAD; // my_coin = 0 would also work here</p>
<p>if you try to create another typedef like this, the compiler will<br>
complain that HEAD is already declared:<br>
typedef enum {HEAD, TAIL} alternate_coin_side;</p>
<p>if you do something like:</p>
<p>typedef enum {PAPER, ROCK, SCISORS} game;<br>
coin_side my_coin = PAPER;</p>
<p>The C compiler won't complain. But Java takes a different approach when<br>
it comes to enums:</p>
<p>class MyClass {<br>
enum Game {PAPER, ROCK, SCISORS};<br>
enum CoinSide {HEAD, TAIL};<br>
void test(){<br>
Game a = Game.PAPER;<br>
Game b = CoinSide.HEAD; // won't compile!<br>
}<br>
}</p>
<p>In that sense, if you write a method accepting a coin side you can only<br>
pass in a CoinSize enum. Not a number. Not another enum type. This is<br>
what I understand by enums. Not symbols related at all in my opinion.</p>
<blockquote>
<blockquote>
<p>They don't spend their time thinking about whether they should be using<br>
symbols or strings. They don't WANT to worry about it!</p>
</blockquote>
<p>Your overarching goal is to coddle developers who write code without<br>
understanding either the language, or the concepts behind their own<br>
code. There is a massive philosophical disjunct here between you and<br>
I, and I think it will never be overcome.</p>
</blockquote>
<p>It is a matter of choosing the right tool. If you're really concerned<br>
about some really small performance improvements you might get by using<br>
symbols instead of strings I would question if Ruby is really the right<br>
language for you.</p>
<p>I'd never consider Ruby or Java to write hard-real-time applications the<br>
same way I wouldn't consider Windows or plain Linux for such task. I'd<br>
most likely use C and Linux + Xenomai patch (if building for desktops)<br>
instead.</p>
<p>When I'm writing Ruby code I don't want to worry about micro performance<br>
improvements. The minimal amount of time I would probably care in<br>
optimizing would be 100ms instead of micro-seconds when I'm writing C<br>
programs that must complete some complex tasks in very short times when<br>
writing real-time tasks.</p>
<blockquote>
<blockquote>
<p>I agree it is unlike to happen. What about another syntax: {{a: 1}} =><br>
{'a' => 1}? Maybe it would worth trying to ask for some syntax change<br>
like this one. We could even add interpolation to it:<br>
{{"value #{computed}": 1}}.</p>
</blockquote>
<p>You'd probably be more likely to succeed with a new %string-style<br>
notation, like %h{a:1, b:2}. Although then again, possibly not.</p>
</blockquote>
<p>That's an idea, yes, but I guess I prefer Thomas' suggestion of using<br>
Map(a: 1, b: 2).</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360172013-02-08T07:30:29Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 07-02-2013 19:15, Matthew Kerwin escreveu:</p>
<blockquote>
<p>On 8 February 2013 03:01, jeremyevans0 (Jeremy Evans)<br>
<<a href="mailto:merch-redmine@jeremyevans.net" class="email">merch-redmine@jeremyevans.net</a> <a href="mailto:merch-redmine@jeremyevans.net" class="email">mailto:merch-redmine@jeremyevans.net</a>><br>
wrote:</p>
<pre><code>phluid61 (Matthew Kerwin) wrote:
> > Take the Sequel library for instance.
>
> No thanks, apparently the authors don't know the difference
between Symbols
> and Strings.
Sequel uses symbol keys instead of string keys intentionally.
Sequel maps SQL features directly to ruby objects, mapping SQL
identifiers (columns/tables/aliases) to ruby symbols and SQL
strings to ruby strings. SQL query results can be thought of as a
mapping of SQL identifiers to the values for each identifier in
the query, thus Sequel uses a hash with symbol keys.
</code></pre>
<p>Sorry, I was being glib.</p>
<p>Interestingly, this is actually an example of Symbols being used<br>
correctly (or at least, not just out-right incorrectly). It's a pity<br>
people see this is a problem to be worked around, rather than a feature.</p>
</blockquote>
<p>I've never complained about Sequel returning symbols. I'm complaining<br>
about symbols not behaving just like regular strings when they're used<br>
as keys in hashes among other usage examples. That's why I never asked<br>
Jeremy to change Sequel's current behavior.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360242013-02-08T08:23:10Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>Sent from my phone, so excuse the typos.<br>
On Feb 8, 2013 8:50 AM, "Rodrigo Rosenfeld Rosas" <a href="mailto:rr.rosas@gmail.com" class="email">rr.rosas@gmail.com</a><br>
wrote:</p>
<blockquote>
<p>If you really believe symbols are similar to enums I guess you haven't<br>
done much C, C++ or Java programming and used enums. Here is the main<br>
reason why enums exist.</p>
</blockquote>
<p>Yes, the reason they are called 'enums' and not 'arbitrary identifiers' is<br>
because they define an explicit, finite, enumerated set of identifiers; as<br>
such an 'enum' is a set of things-that-are-like-symbols. But ´head´ is not,<br>
and should never be, equal to 0 or 1 or whatever. The fact that C reveals<br>
its implementation in this way is an artifact of C, not the concept of<br>
enums in general.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360262013-02-08T08:59:10ZAnonymous
<ul></ul><p>Hi,</p>
<p>During early stage of 1.9 development, I tried to make symbols and<br>
strings behave same (at least similar), and it had broken too many<br>
programs. I understand your problem but it's not worth raising huge<br>
compatibility issues.</p>
<pre><code> matz.
</code></pre> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360272013-02-08T09:29:09Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 07-02-2013 21:58, Yukihiro Matsumoto escreveu:</p>
<blockquote>
<p>Hi,</p>
<p>During early stage of 1.9 development, I tried to make symbols and<br>
strings behave same (at least similar), and it had broken too many<br>
programs. I understand your problem but it's not worth raising huge<br>
compatibility issues.</p>
<pre><code> matz.
</code></pre>
</blockquote>
<p>Thank you for your feedback, Matz. I'd really never suspect such a<br>
change could break so many programs...</p>
<p>I'm really curious what kind of programs rely on symbols behaving<br>
differently from strings. But I guess you won't remember which programs<br>
would be them, will you?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360282013-02-08T10:23:17Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul></ul><p>On Feb 7, 2013, at 10:43, David MacMahon <a href="mailto:davidm@astro.berkeley.edu" class="email">davidm@astro.berkeley.edu</a> wrote:</p>
<blockquote>
<p>I think the number of real world uses of something like:</p>
<p>{:a => 0, 'a' => 1}</p>
<p>is likely to be very small.</p>
</blockquote>
<p>Every time you run <code>gem</code> you use a hash that contains both symbol and string keys used for different purposes.</p>
<p>In ~/.gemrc symbols are used for configuration options while strings are used for command default arguments.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360292013-02-08T10:23:17ZAnonymous
<ul></ul><p>Hi,</p>
<p>In message "Re: <a href="/issues/7792">[ruby-core:52017]</a> Re: [ruby-trunk - Feature <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Make symbols and strings the same thing (Rejected)" href="https://redmine.ruby-lang.org/issues/7792">#7792</a>] Make symbols and strings the same thing"<br>
on Fri, 8 Feb 2013 09:26:38 +0900, Rodrigo Rosenfeld Rosas <a href="mailto:rr.rosas@gmail.com" class="email">rr.rosas@gmail.com</a> writes:</p>
<p>|Thank you for your feedback, Matz. I'd really never suspect such a<br>
|change could break so many programs...<br>
|<br>
|I'm really curious what kind of programs rely on symbols behaving<br>
|differently from strings. But I guess you won't remember which programs<br>
|would be them, will you?</p>
<p>It was long long ago. But some programs distinguished symbols and<br>
strings as hash keys, for example.</p>
<p>Symbols are taken from Lisp symbols, and they has been totally<br>
different beast from strings. They are not nicer (and faster)<br>
representation of strings. But as Ruby stepped forward its own way,<br>
the difference between symbols and strings has been less recognized by<br>
users.</p>
<pre><code> matz.
</code></pre> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360302013-02-08T10:53:17Zdavid_macmahon (David MacMahon)davidm@astro.berkeley.edu
<ul></ul><p>On Feb 7, 2013, at 5:15 PM, Eric Hodel wrote:</p>
<blockquote>
<p>On Feb 7, 2013, at 10:43, David MacMahon <a href="mailto:davidm@astro.berkeley.edu" class="email">davidm@astro.berkeley.edu</a> wrote:</p>
<blockquote>
<p>I think the number of real world uses of something like:</p>
<p>{:a => 0, 'a' => 1}</p>
<p>is likely to be very small.</p>
</blockquote>
<p>Every time you run <code>gem</code> you use a hash that contains both symbol and string keys used for different purposes.</p>
<p>In ~/.gemrc symbols are used for configuration options while strings are used for command default arguments.</p>
</blockquote>
<p>Well, that's one! In my defense, one is a very small number even if that one is of very large consequence. :-)</p>
<p>Just to play Devil's advocate, could that not be separated into two different hashes: one for config options and one for command default arguments? You have given semantic meaning to (the class of) the key. Isn't that akin to treating the primary key of a database record in a non-opaque manner?</p>
<p>Dave</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360312013-02-08T10:59:21Zspatulasnout (B Kelly)billk@cts.com
<ul></ul><p>Rodrigo Rosenfeld Rosas wrote:</p>
<blockquote>
<p>I'm really curious what kind of programs rely on symbols behaving<br>
differently from strings.</p>
</blockquote>
<p>One example:</p>
<p>Since symbols aren't garbage collected, my Ruby-based RPC system<br>
is designed by default to convert symbols in incoming messages to<br>
strings instead. (PacketBuf.preserve_symbols_on_extract = false)</p>
<p>This has led to sending certain internal messages with names<br>
consisting of symbols instead of strings. These messages cannot<br>
be spoofed by an external source, as there's no way for a remote<br>
sender to produce messages locally containing symbols.</p>
<p>(If not for the garbage collection problem, I would have designed<br>
the system to preserve externally generated symbols, and so would<br>
have then required a different approach to distinguish internal<br>
vs. external message names. So current design is arbitrary in<br>
that sense, but nevertheless, the symbol/string distinction is<br>
being put to use.)</p>
<p>Regards,</p>
<p>Bill</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360472013-02-08T16:23:17Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Em 07-02-2013 23:57, Bill Kelly escreveu:</p>
<blockquote>
<p>...but nevertheless, the symbol/string distinction is being put to use.)</p>
</blockquote>
<p>Thanks for letting me know, Bill.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=360662013-02-09T09:53:32Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul></ul><p>On Feb 7, 2013, at 17:37, David MacMahon <a href="mailto:davidm@astro.berkeley.edu" class="email">davidm@astro.berkeley.edu</a> wrote:</p>
<blockquote>
<p>Just to play Devil's advocate, could that not be separated into two different hashes: one for config options and one for command default arguments? You have given semantic meaning to (the class of) the key. Isn't that akin to treating the primary key of a database record in a non-opaque manner?</p>
</blockquote>
<p>Two hashes would not be backwards compatible with previous versions of RubyGems. I'm hesitant to change the format of a configuration file and break downgrades between RubyGems versions.</p>
<p>It would be more confusing to new users. Now we can tell users "paste '…' into ~/.gemrc to do …" and it will work. They don't need to know anything about ruby or yaml to do this.</p>
<p>If matz decides that we should break backwards compatibility in this manner I will change my mind.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=361522013-02-12T09:23:17Zdavid_macmahon (David MacMahon)davidm@astro.berkeley.edu
<ul></ul><p>On Feb 8, 2013, at 4:50 PM, Eric Hodel wrote:</p>
<blockquote>
<p>On Feb 7, 2013, at 17:37, David MacMahon <a href="mailto:davidm@astro.berkeley.edu" class="email">davidm@astro.berkeley.edu</a> wrote:</p>
<blockquote>
<p>Just to play Devil's advocate, could that not be separated into two different hashes: one for config options and one for command default arguments? You have given semantic meaning to (the class of) the key. Isn't that akin to treating the primary key of a database record in a non-opaque manner?</p>
</blockquote>
<p>Two hashes would not be backwards compatible with previous versions of RubyGems. I'm hesitant to change the format of a configuration file and break downgrades between RubyGems versions.</p>
<p>It would be more confusing to new users. Now we can tell users "paste '…' into ~/.gemrc to do …" and it will work. They don't need to know anything about ruby or yaml to do this.</p>
<p>If matz decides that we should break backwards compatibility in this manner I will change my mind.</p>
</blockquote>
<p>I was not trying to induce change. I think my follow-on query would have been more appropriate for ruby-talk rather than ruby-core. I will (try to) keep my ruby-core postings more on topic.</p>
<p>Thanks for the explanation,<br>
Dave</p>
<p>P.S. Sorry if this gets out more than once. I'm in the midst of an involuntary email "transition".</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=377712013-03-21T00:02:04Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Just another confusion caused by different behavior of strings vs symbols: <a href="https://github.com/blog/1440-today-s-email-incident" class="external">https://github.com/blog/1440-today-s-email-incident</a></p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=377822013-03-21T12:09:59ZStudent (Nathan Zook)blogger@pierian-spring.net
<ul></ul><p>The problem is not "confusion", it is that there is an apparent effort to rework core features in a massive framework in little pieces. These things don't fail in isolation--it is an error to attempt to fix them in isolation.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=377932013-03-21T22:01:13Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>What I meant is that most people only use symbols as an identifier that could be a just a string as well. If you look at the code semanthic you'll notice that they don't really care about symbol vs strings differences. They just want an identifier but then they have to be concerned about their differences all over the code even when they don't want this because different pieces will have different opinions about if symbols or strings should be used for that case. Sometimes they only happen to use symbols because of the convenience of the new hash better looking syntax. I'm just trying to convince Matz to evaluate once again the possibility of making symbols behave like string.freeze! or simply like regular strings even if it would break backward compatibility... I still believe all the confusion created by their differences will keep happening and breaking compatibility for good in this case makes sense to me. Please reconsider this ticket...</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=377942013-03-21T22:04:31Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>Also, as a nice side effect we wouldn't even have to worry about garbage collecting symbols to avoid DoS as they would be automatically collected just like strings. If MRI wants to keep the original notion of symbols as an internal implementation detail, that's fine, but this shouldn't leak to end users...</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=379212013-03-26T00:14:12ZStudent (Nathan Zook)blogger@pierian-spring.net
<ul></ul><p>Actually, rails trusts symbols at times in ways that it does not trust strings. This is the source of a recent security issue or two, as it was assumed that symbols creation would not be directed from outside data.</p>
<p>Better would have been to have run in safe mode 1, or to have watched the tainted property directly.</p>
<p>Without studying this most recent issue in detail, it looks like the rails devs have opted for rapid, "mostly right" instead of deeply-analysed, thoroughly-vetted solutions. Given the nature of some of these issues, that was almost certainly correct as an initial response.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=379462013-03-27T05:46:27Zalexeymuranov (Alexey Muranov)
<ul></ul><p>Student (Nathan Zook) wrote:</p>
<blockquote>
<p>Actually, rails trusts symbols at times in ways that it does not trust strings. This is the source of a recent security issue or two, as it was assumed that symbols creation would not be directed from outside data.</p>
</blockquote>
<p>In Rails, the <code>Hash#symbolize_keys!</code> method looks somewhat unacceptable to me.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=380332013-03-30T02:34:17ZStudent (Nathan Zook)blogger@pierian-spring.net
<ul></ul><p>Yep. If to_sym threw or nilled on previously unknown symbols, or at least on tainted data, this would be okay. Otherwise, it is a serious security problem.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=381652013-04-03T19:06:35Zwardrop (Tom Wardrop)tom@tomwardrop.com
<ul></ul><p>=begin<br>
= To Summarise...</p>
<p>== Symbol Differences</p>
<p>=== Immutable<br>
A symbol is an alias for a numeric ID. The symbol representation of that numeric ID can never change.</p>
<p>=== Not garbage collected<br>
An extension of the previous point. Garbage collecting symbol's would break the fact that symbol's are an alias for a specific numeric ID.</p>
<p>=== Semantically different<br>
The type difference between a String and a Symbol can be used in program logic.</p>
<p>== The Problem<br>
((<em>And yes, there is clearly a problem! You can argue the solution.</em>))</p>
<p>=== Inconsistance use<br>
It's virtually impossible to reliably determine when to use a Symbol or a String. Today, Symbol might be the logical choice for scenario X, but tomorrow you're looking up those Symbols with user-entered data, or reading them in from a file, etc. Programs change, requirements change, everything changes.</p>
<p>=== Library incompatibility<br>
As a consequence of the previous point, combined with different levels of programmer experience and plain personal opinion, libraries will always contain incompatibility.</p>
<p>=== Unignorable (((<em>It's a real word, I swear</em>)))<br>
As a consequence of the previous two, even if you only use one or the other, unless you want to avoid using 3rd party code, stdlib, or even ruby-core, there's no way to ignore the fact that Symbol's are different and completely incompatible with String's. Pita.</p>
<p>== The Solution<br>
Or more to the point, what criteria does a solution need to meet. I don't believe any solution can resolve all the problems, while maintaing full backwards compatibility. Therefore, I see there being a short-term solution, i.e. minor version release of 2.x, and a long term solution, i.e 3.0.</p>
<p>I think the Ruby project needs to maintain a list of desired backwards-incompatible changes, so these can be rolled up into one big 3.0 release. Ruby can't be backwards compatible forever, otherwise it'll slowly fade into insignificance... hey Microsoft.</p>
<p>=== Short Term<br>
I don't think there is one. HashWithIndifferentAccess will not solve the problem with hash keys. You'll just go from coercing Symbols to String and vice versa, to coercing Hash to HashWithIndifferentAccess, and back again, and there's no way we can make the differences ignorable to those libraries that don't care, while still satisfying those libraries that do care. Anything we change will probably only help to dig us all a deeper hole.</p>
<p>The short term solution is to accept there's a problem, and that anything backwards-compatible isn't worth changing.</p>
<p>=== Long Term<br>
I propose the remainder of this thread should focus on a long term solution that solves ALL the problems without worrying about full backwards-compatibility, and for everyone to accept that there is indeed a problem with the existence and/or current implementation of Strings and Symbols. Getting rid of Symbols, making Symbols a sub-class of String, whatever. Let's talk about that now, please. It's clear that even Matz is unsatisfied with the current situation.</p>
<p>=end</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=381692013-04-03T19:44:13Zphluid61 (Matthew Kerwin)matthew@kerwin.net.au
<ul></ul><p>=begin<br>
In that case, I suggest that the long term solution is education.</p>
<p>By the way: "((<em>A symbol is an alias for a numeric ID.</em>))" Not entirely true (otherwise we could argue for Symbol#to_i or even Symbol#to_int) A symbol represents an immutable concept, analogous to a number (i.e. 3 is always 3, even outside of Ruby; so :to_s is always :to_s). The numeric ID is an implementation detail.</p>
<p>Also, it's spelled "Summarise" with an 'a' (or "Summarize" in America.) ;)<br>
=end</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=381742013-04-03T21:01:04Zwardrop (Tom Wardrop)tom@tomwardrop.com
<ul></ul><p>No that's spelt correctly. I sadly couldn't embed any pictures of palm trees and coconuts ;). Fixed, thanks.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=381782013-04-03T22:29:22Zspatulasnout (B Kelly)billk@cts.com
<ul></ul><p>wardrop (Tom Wardrop) wrote:</p>
<blockquote>
<p>=== Immutable<br>
A symbol is an alias for a numeric ID. The symbol representation of that<br>
numeric ID can never change.</p>
</blockquote>
<p>As Matthew Kerwin noted, the numeric ID is an implementation detail; and<br>
indeed, the IDs already do change:</p>
<p>$ ruby -e "p [:foo.object_id, :bar.object_id]"<br>
[143928, 144008]</p>
<p>$ ruby -e "p [:bar.object_id, :foo.object_id]"<br>
[143928, 144008]</p>
<blockquote>
<p>=== Not garbage collected<br>
An extension of the previous point. Garbage collecting symbol's would break<br>
the fact that symbol's are an alias for a specific numeric ID.</p>
</blockquote>
<p>Presumably this could only affect programs which retain the object_id<br>
of a symbol past the point where the symbol itself is no longer<br>
referenced by the program, and which then expect to be able to compare<br>
that object_id with the object_id of the equivalent symbol after it<br>
has been GC'd and re-interned.</p>
<p>Assuming the rest of the GC-related problems have been solved, such as<br>
marking any symbols interned by ruby extensions as non-GC-able, then<br>
we should only need wonder how much pure ruby code exists that, during<br>
the lifetime of a given ruby interpreter process, is storing and<br>
comparing symbol object_ids rather than the symbols themselves.</p>
<p>If much such code indeed exists in production environments, then<br>
presumably symbol GC could be introduced as a VM startup option,<br>
eventually becoming the default after the legacy behavior has gone<br>
through a deprecation phase.</p>
<p>It's not evident to me that a solution to the symbol GC issue needs<br>
to be bundled with solution(s) for symbol/string equivalence issues,<br>
however.</p>
<p>Regards,</p>
<p>Bill</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=381922013-04-04T07:42:59Zwardrop (Tom Wardrop)tom@tomwardrop.com
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/442">@spatulasnout (B Kelly)</a> Yes on your first point. One should always compare :symbol with :symbol rather than by their internal ID, so I'd say that any code using the internal ID's deserves to break. I imagine it would be hardly any, other than the interpreter itself.</p>
<p>So on that note, I think you're right. Garbage collecting symbol's could be implemented while maintaining backwards compatibility. That may address the technical implications such as the potential for DoS attacks. As you said, this could safely be implemented as a startup option, or potentially even a runtime option.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=477862014-07-15T15:39:02ZAjedi32 (Andrew M)andrewm.bpi@gmail.com
<ul></ul><p>So now that Symbol GC is implemented (<a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: [PATCH]Symbol GC (Closed)" href="https://redmine.ruby-lang.org/issues/9634">#9634</a>), does that change anything about the viability of this proposal?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=482612014-08-08T20:02:16Zeloyesp (Eloy Esp)eloyesp@gmail.com
<ul></ul><p>I think the proposal is goood, if the change is better to new programmers it means it is better for all programmers, (because eventually the old experienced ruby programmer will die) and we will be adapting the people to the code instead of the other way around (that is not a good practice).</p>
<p>As I understand, the proposed change can be read as:</p>
<ul>
<li>Currently there is an exception in the language for strings as hash keys (they are duped and frozen).</li>
<li>This behaviour is unexpected for new rubysts and for not so new (I learned that yesterday, and I worked with ruby for 4+ years).</li>
<li>Using strings as symbols for hash keys is a headache for many programmers. (there are a lot of libraries to make this easier).</li>
<li>There is a lot of libraries written with the traditional way in mind. Thus all the gems that stores in the same hash strings and symbols could break if we change the exception.</li>
</ul>
<p>Given the change will break things, but will make things better, why not plan it for ruby 3.0?</p>
<p>The only use-case that will break things is:</p>
<pre><code>hash = {}
hash['key'] = value
hash[:key] = other_value
</code></pre>
<p>We can add a warning when you do something like this and make the change a year after that.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=629862017-02-16T01:22:45Zsubtileos (Daniel Ferreira)
<ul></ul><p>Hi Bill</p>
<blockquote>
<p>One example:</p>
<p>Since symbols aren't garbage collected, my Ruby-based RPC system<br>
is designed by default to convert symbols in incoming messages to<br>
strings instead. (PacketBuf.preserve_symbols_on_extract = false)</p>
<p>This has led to sending certain internal messages with names<br>
consisting of symbols instead of strings. These messages cannot<br>
be spoofed by an external source, as there's no way for a remote<br>
sender to produce messages locally containing symbols.</p>
<p>(If not for the garbage collection problem, I would have designed<br>
the system to preserve externally generated symbols, and so would<br>
have then required a different approach to distinguish internal<br>
vs. external message names. So current design is arbitrary in<br>
that sense, but nevertheless, the symbol/string distinction is<br>
being put to use.)</p>
</blockquote>
<p>With symbols being garbage collected now is this functionality broken or are you still relying on symbols over strings for your solution?</p>
<p>Thanks,</p>
<p>Daniel</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=629882017-02-16T02:21:23Zspatulasnout (B Kelly)billk@cts.com
<ul></ul><p>Hi Daniel,</p>
<p>Daniel Ferreira wrote:</p>
<blockquote>
<blockquote>
<p>(If not for the garbage collection problem, I would have designed<br>
the system to preserve externally generated symbols, and so would<br>
have then required a different approach to distinguish internal<br>
vs. external message names. So current design is arbitrary in<br>
that sense, but nevertheless, the symbol/string distinction is<br>
being put to use.)</p>
</blockquote>
<p>With symbols being garbage collected now is this functionality broken<br>
or are you still relying on symbols over strings for your solution?</p>
</blockquote>
<p>I've continued using the aforementioned RPC system without enabling<br>
the setting that would allow it to recreate symbols on the receiving<br>
end.</p>
<p>So it continues to work as it did before (if the remote sends symbols,<br>
they appear only as strings locally.)</p>
<p>I will say however that on the balance, in the time I've been using<br>
this system, it can feel sub-optimal to have to keep track of which<br>
parameters are symbols and which are strings. I'd say my primary<br>
motivation for using producing symbols on the sending end is Ruby's<br>
convenient hash syntax:</p>
<p>result = some.rpc_method(foo:123, bar:"baz")</p>
<p>I find that i like the syntax enough, that I'll put up with having<br>
to think about when those symbols will have been turned into strings<br>
down the line.</p>
<p>But it would be nice to not have to keep track of that detail.</p>
<p>Regards,</p>
<p>Bill</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=629892017-02-16T02:33:55Zsubtileos (Daniel Ferreira)
<ul></ul><blockquote>
<p>result = some.rpc_method(foo:123, bar:"baz")</p>
<p>I find that i like the syntax enough, that I'll put up with having<br>
to think about when those symbols will have been turned into strings<br>
down the line.</p>
</blockquote>
<p>I believe it is time now with the advent of Ruby 3 to revisit this feature request.<br>
Although maybe not quite like it is stated right now.</p>
<p>What are your feelings about it?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=670742017-10-05T18:19:33Zsheerun (Adam Stankiewicz)sheerun@sher.pl
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/10">@shyouhei (Shyouhei Urabe)</a> <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/13">@matz (Yukihiro Matsumoto)</a> Could this be revisited as ruby now has frozen strings? They behave pretty much the same as symbols.</p>
<p>Here's an article worth read: <a href="http://blog.arkency.com/could-we-drop-symbols-from-ruby/" class="external">http://blog.arkency.com/could-we-drop-symbols-from-ruby/</a></p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=671102017-10-07T04:15:00Zshevegen (Robert A. Heiler)shevegen@gmail.com
<ul></ul><p>I found the old issue here too from the blog article. :)</p>
<p>However had, I do not think that frozen strings would be the same (semantic-wise) as Symbols so I am<br>
not sure that this would lead to a reconsideration of the String/Symbol distinction.</p>
<p>I personally am fine with the way how Symbols behave as-is; I do also understand that other people<br>
think of the distinction somewhat annoying - the best example may be HashWithIndifferentAccess :D</p>
<p>I mean, that is so long to write out, I wonder how people can use it over "Hash"... but I understand<br>
the problem situation. People want to squeeze out whatever is faster, and also not have to think "when<br>
to use strings and when to use symbols" - it's like an obsession and somewhat understandable the larger<br>
(and perhaps slower) a codebase becomes + amount of users of said codebase. The mental "cognitive load"<br>
will remain as long as ruby has a string-versus-symbols distinction, but I myself have come to like<br>
symbols. :cat and :dog versus 'cats' and 'dogs'.</p>
<p>My only minor concern with the distinction was whether I would be able to treat Symbols as String-like<br>
for some string-like operations, such as via :foobar[1,2] - but that is already possible. Walks<br>
like a duck, quacks like a duck, is a symbolized duck. Actually, an even more radical solution would<br>
be to get rid of Symbols altogether, since that would simplify the usage instantly. Are frozen strings<br>
and symbols really as fast? I have no benchmarks but I think that symbols may still be faster, since<br>
they may do more - but since I have no benchmark, this is just idle speculation. I mention this<br>
because the old proposal here wrote "make symbols and strings the same thing" but you could also<br>
have a proposal that would "remove symbols" ... :P</p>
<p>Matz explained the origin of Symbols back then here:</p>
<p><a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/52019" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/52019</a></p>
<p>I think Symbols became more popular after the Dave-book stating that they are much faster<br>
in Hashes than string-object, so since people like speed, they'd use Symbols a lot. I<br>
like symbols a lot too, but mostly because ... it's less to type! I can also enable some<br>
specific behaviour depending on input arguments given to methods. This may be a very<br>
akward usage example but I like it.</p>
<p>Perhaps you may have a chance to see the situation be revisited for ruby 3.x but I myself<br>
think that the Symbols will stay as they are for other reasons, including inertia. Another<br>
factor to be considered is how ruby "views" the its world - and I think that the original<br>
idea never was to expose symbols as-is and instead may have users focus only on strings<br>
primarily.</p>
<p>Btw here is a short discussion at stackoverflow about symbols in lisp:</p>
<p><a href="https://stackoverflow.com/questions/8846628/what-exactly-is-a-symbol-in-lisp-scheme" class="external">https://stackoverflow.com/questions/8846628/what-exactly-is-a-symbol-in-lisp-scheme</a></p>
<p>What I gather there is that the primary use case is indeed due to speed (or "light-weight<br>
execution") compared to alternatives.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689712017-12-26T08:36:30Zdsferreira (Daniel Ferreira)
<ul></ul><p>If we are considering breaking backwards compatibility in ruby 3.0 with removal of API like IO.read which is all over let’s fix this symbol vs string issue once and for all shall we?<br>
Ruby programmers will be much happier.<br>
Why don’t we start a new issue maybe in common ruby to come up with a broad solution?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689742017-12-26T08:43:00Zdsferreira (Daniel Ferreira)
<ul></ul><p>If we do want to keep symbols as part of ruby API what about considering a new syntax for symbols and leave the current symbol syntax to be identified as string literals or just strings?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689812017-12-26T09:08:38Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p><a href="mailto:danieldasilvaferreira@gmail.com" class="email">danieldasilvaferreira@gmail.com</a> wrote:</p>
<blockquote>
<p>If we are considering breaking backwards compatibility in ruby<br>
3.0 with removal of API like IO.read which is all over let’s</p>
</blockquote>
<p>Removal of IO.read? I hope you're not misinterpreting my <a href="/issues/14239">[ruby-core:84461]</a><br>
response to <a href="https://bugs.ruby-lang.org/issues/14239" class="external">https://bugs.ruby-lang.org/issues/14239</a><br>
I only want to warn on the IO.read("| command") case,<br>
not remove the whole thing.</p>
<p>Anyways, I do not have much opinion on symbols/strings;<br>
but I hate breaking compatibility.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689842017-12-26T09:24:39Zdsferreira (Daniel Ferreira)
<ul></ul><p>It seems that what is in question to be removed in ruby 3.0 is the pipe feature associated to Kernel#open and related API not the all method.</p>
<p>Still breaking backwards compatibility though.</p>
<p>Sorry for misreading it and thanks Eric for pointing me out the error.</p>
<p><a href="https://bugs.ruby-lang.org/issues/14239" class="external">https://bugs.ruby-lang.org/issues/14239</a></p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689852017-12-26T09:36:32Znormalperson (Eric Wong)normalperson@yhbt.net
<ul></ul><p>Daniel Ferreira <a href="mailto:subtileos@gmail.com" class="email">subtileos@gmail.com</a> wrote:</p>
<blockquote>
<p>Why isn’t your reply on the issue tracker?</p>
</blockquote>
<p>It should be, I see it. Might take some minutes for mail to propagate.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689942017-12-26T14:33:26Zko1 (Koichi Sasada)
<ul></ul><blockquote>
<p>It seems that what is in question to be removed in ruby 3.0 is the pipe feature associated to Kernel#open and related API not the all method.</p>
<p>Still breaking backwards compatibility though.</p>
</blockquote>
<p>Important point is, we can know the breaking compatibility with exceptions. If we remove some method or feature (like <code>IO.open('|...')</code> we (the application programmer) can understand it was obsolete.</p>
<p>However, this case, program breaks silently and difficult to debug.</p>
<p>Personally I like this idea and if I have a time machine, I wanted to suggest this idea at 199x.<br>
If we need to introduce breaking compatibility, we need to make transition path.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689952017-12-26T15:11:34Zdsferreira (Daniel Ferreira)
<ul></ul><blockquote>
<p>If we need to breaking compatibility, we need to make transition path</p>
</blockquote>
<p>Thanks Koichi.<br>
I totally agree with you and Eric about worries on breaking backwards compatibility.<br>
I was wondering if it wouldn’t be possible to use some kind of transitional flag like:</p>
<p><code># frozen_string_literal: true</code><br>
Or<br>
<code>--enable-frozen-string-literal</code></p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689962017-12-26T15:43:41Zko1 (Koichi Sasada)
<ul></ul><blockquote>
<p>I was wondering if it wouldn’t be possible to use some kind of transitional flag like:</p>
</blockquote>
<p>Please consider transition path for users who are using symbol and string difference like:</p>
<pre><code>key = ...
...
when key
case String
...
case Symbol
...
end
</code></pre>
<p>How to find out such programs?</p>
<p>frozen-strign-literal, we can know issues by seeing <code>FrozenError</code> (and also <code>debug_frozen_string_literal</code> is supported to find out the problem).</p>
<p>If you (or someone) find out any good transition path, we think we can consider again.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=689982017-12-26T19:30:27Zdsferreira (Daniel Ferreira)
<ul></ul><p>Hi Koichi.</p>
<p>I’ve been thinking about the challenge you put me.<br>
What if we add as a transition path the method:<br>
<code>String#old_symbol</code>.</p>
<p>Then we could use it in the <code>Symbol::===(var)</code><br>
and we would warn if <code>var.is_a?(String) && var.old_symbol == true</code></p>
<p>What do you think?<br>
Something missing?</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=690062017-12-26T21:45:05Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>I'm 100% against merging Symbols and Strings. Symbols and Strings have always represented different concepts. Symbols are a simple way to get a unique named identifier, and Strings represent arbitrary data/text. In some cases, you need to convert from one or the other, generating an identifier from the content of data/text (String->Symbol), or treating the name of the identifier as data/text (Symbol->String). But Strings and Symbols represent different concepts and should be treated differently.</p>
<p>Merging Symbols and Strings would break libraries that do treat them differently in ways that would be almost impossible to fix without making APIs very ugly (and obviously breaking backwards compatibility).</p>
<p>The main argument I've heard for combining Strings and Symbols is to save some characters when typing, as shown in the initial post for this issue. I don't consider this a major problem, but if other people really want to save those characters, I think it would be better to add a terser form of string literals, as opposed to completely breaking symbols.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=690072017-12-26T22:11:10Zdsferreira (Daniel Ferreira)
<ul></ul><blockquote>
<p>But Strings and Symbols represent different concepts and should be treated differently.</p>
</blockquote>
<p>Jeremy I agree with you on this and that is one of the reasons, possibly the biggest reason, why I think it will make a huge difference if we stop using symbols as if they were plain simple strings like I see scattered all over the place.</p>
<p>Let’s put symbols where they belong shall we?</p>
<p>I ask again: Shall we open a new issue under common ruby with a broader purpose?</p>
<p>The reality is that converting current symbol’s syntax to be used as yet another string’s syntax will keep intact the great majority of the code currently in production.</p>
<p>From this discussions we don’t see many examples of proper use of symbols as such.</p>
<p>I believe we can fix this and keep Symbols and Strings as part of ruby API in a much better way.</p>
<p>A new syntax for symbols is the first thing that comes to my mind or a plain <code>Symbol.new</code> instantiation.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=690492017-12-27T17:35:55Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>dsferreira (Daniel Ferreira) wrote:</p>
<blockquote>
<blockquote>
<p>But Strings and Symbols represent different concepts and should be treated differently.</p>
</blockquote>
<p>Jeremy I agree with you on this and that is one of the reasons, possibly the biggest reason, why I think it will make a huge difference if we stop using symbols as if they were plain simple strings like I see scattered all over the place.</p>
</blockquote>
<p>I think it's far more common to use symbols correctly than incorrectly. The only time I see confusion is when using things like HashWithIndifferentAccess. That more than anything else has probably contributed to some ruby programmers not understanding what the difference is.</p>
<blockquote>
<p>I ask again: Shall we open a new issue under common ruby with a broader purpose?</p>
</blockquote>
<p>You are free to open an issue. However, considering this has already been rejected, I don't see the point.</p>
<blockquote>
<p>The reality is that converting current symbol’s syntax to be used as yet another string’s syntax will keep intact the great majority of the code currently in production.</p>
</blockquote>
<p>"Extraordinary claims require extraordinary evidence"</p>
<blockquote>
<p>From this discussions we don’t see many examples of proper use of symbols as such.</p>
</blockquote>
<p>I'm not sure if this discussion is reflective of symbol usage in most ruby code. In most cases I see symbols used correctly, as named identifiers. In most cases I see strings used correctly, as text/data. There are a few cases where I see them used incorrectly, mostly at the borders of programs, where input is always provided as strings. However, that's a security sensitive area and care should be taken before converting any strings to symbols.</p>
<blockquote>
<p>I believe we can fix this and keep Symbols and Strings as part of ruby API in a much better way.</p>
<p>A new syntax for symbols is the first thing that comes to my mind or a plain <code>Symbol.new</code> instantiation.</p>
</blockquote>
<p>This does not make sense to me. If you introduce a new syntax for symbols, most people won't switch to it unless they don't care about backwards compatibility at all. If by some miracle the community does switch to it, you'll end up the same situation we currently have eventually.</p>
<p>You've already recognized that strings and symbols are different concepts and have different purposes. Therefore the only reason make the current symbol syntax represent strings if you want a terser syntax for strings. In which case instead of breaking backwards compatibility, it would make more sense to introduce a new separate terser syntax for strings.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=690532017-12-27T19:52:27Zdsferreira (Daniel Ferreira)
<ul></ul><blockquote>
<p>I think it's far more common to use symbols correctly than incorrectly. The only time I see confusion is when using things like HashWithIndifferentAccess.</p>
</blockquote>
<p>Let me give you just this example to show you how things are out of control:</p>
<p><code>alias_method :foo, :bar</code><br>
<code>alias_method "foo", "bar"</code></p>
<p>Both usages are allowed.</p>
<p>This kind of interface is present in many places.<br>
You have it in ruby core and you have it even more in gems and even more in applications.<br>
And there will be no way you can change that line of thought scattered throughout the community.<br>
We are using strings and symbols interchangeably and this is an evidence.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=690562017-12-27T20:28:59ZAjedi32 (Andrew M)andrewm.bpi@gmail.com
<ul></ul><p>Leaving aside the issue of semantics for a moment, can anyone provide a real, concrete example of a situation where symbols could not trivially be replaced with strings without negatively impacting the functionality of the surrounding code?</p>
<p>I'm having trouble thinking of such a scenario that's not obviously contrived.</p> Ruby master - Feature #7792: Make symbols and strings the same thinghttps://redmine.ruby-lang.org/issues/7792?journal_id=690572017-12-27T20:39:48Zdsferreira (Daniel Ferreira)
<ul></ul><blockquote>
<p>Leaving aside the issue of semantics for a moment, can anyone provide a real, concrete example of a situation where symbols could not trivially be replaced with strings without negatively impacting the functionality of the surrounding code?</p>
</blockquote>
<p>Koichi’s challenge for a transition path is the example we have to support so far:</p>
<pre><code>key = ...
...
when key
case String
...
case Symbol
...
end
</code></pre>