From: Rick DeNatale Date: 2007-05-15T23:28:05+09:00 Subject: Re: Why was the "Symbol is a String"-idea dropped? Not responding to any particular posting. One of the false memes that some folks on this thread seem to hold is that Symbols are integers. They aren't. Any more than they are strings. A given ruby symbol has both a string and an integer representation, which can be obtained by using the to_s, and to_i But one would't say that the object 1.2 is a string because it has a string representation, or that the object "123" was an integer because it has an integer representation. The essential fact about symbols is that if two symbols have the same string representation they are the same object, and that two different symbols have two different integer representations. Or more formally sym1.to_s == sym2.to_s iff sym1.object_id == sym2.object_id sym1.to_i == sym2.to_i iff sym1.object_id == sym2.object_id One way to implement this is to keep internal tables which map the string and integer representations of symbols to each other, and to have functional mappings between the object_ids and integer representations of symbols. This is how ruby does it. Creating a symbol from a string consists of looking for the string in the mapping from strings to integer representations, and if it's not found assigning the next integer rep and adding the string and integer rep to the internal tables. This operation, called interning, happens either at parse time when :foo is encountered, or later when an expression like 'foo'.to_sym is executed. The meme that "Symbols are Integers" probably lingers from an earlier version of Ruby before there was an actual Symbol class. Back then, symbols really were instances of Fixnum, but no more. This lives on vestigially in that Symbol does have a to_int method as well as to_i, but to_int is deprecated, using it produces a warning : rick@frodo:~$ ruby -w -e"p :sym.to_int" -e:1: warning: treating Symbol as an integer 10409 while to_i does not. rick@frodo:~$ ruby -w -e"p :sym.to_i" 10409 Other languages, like Smalltalk, with similar concepts don't associate integer representations with Symbols, in these languages the internal mapping simply maps string representations to object id's, or to the symbol objects themselves. I suspect that this feature of Ruby symbols is simply due to the earlier implementation. Now what are the useful properties of Symbols: 1. Detecting whether or not two symbols are equal is as fast as comparing their object_ids. This is an O(1) operation. Detecting whether or not two strings are equal requires a scan of both strings until either an unequal character is found or the end of both strings is reached. This is an O(n) operation. 2. Having 1000 'instances' of a symbol with a particular string representation takes no more space than having 1 Property 1 means that things like hashes with symbol keys are somewhat faster than hashes with string keys. This is why symbols are used as method selectors, since dispatching a method call requires repeated lookup in the method tables going up the inheritance chain. This is a win if the key is looked up multiple times, there is an initial cost of interning the symbol (which essentially consists of looking for the string representation in an internal global symbol table) but this cost is amortized over subsequent lookups. It seems that the HashWithIndifferentAccess class added by Rails in ActiveSupport, which allows symbols and strings to be used interchangeably as keys, doesn't actually take advantage of this since it uses symbols converted to strings as the actual keys rather than the other way around. This provides a bit of syntactic sugar, without getting either the performance or space advantages of using symbols. As for incompatibilies caused by the experiment, I'm not sure exactly what Matz and the core team ran into but certainly this would break code like: case arg when String # do something when Symbol # do something else end Code like this exhibits the fragility of doing discrimination based on classes in the face of refactoring. -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/