Andrea Dallera wrote in post #969438:
Ruby has both mutable and immutable strings. A mutable string is
declared as "string". An immutable string is declared as :string and in
ruby is called a 'symbol'. So, no, there is no way for "string" to
behave as :string, since that's by design.
This is a very misleading description, so I'll bite.
Strings and Symbols are two completely different things in Ruby. In Ruby
1.9, Symbols have gained some more string-like behaviour(*), but they're
still fundamentally different.
Symbols are objects intended for labelling things (e.g. method names,
hash keys). The main property of Symbols is that there only ever exists
one Symbol object which represents the same label, i.e. the same
sequence of characters.(**)
So when your program loads, and it uses the symbol :foo, which hasn't
been used before, then a new symbol called :foo is created in the symbol
table. But every other future use of :foo always returns the same
object.
This makes symbols very cheap to test for equality, because:
* Two symbols are the same iff they have the same object_id
* Two symbols are different iff they have different object_id
So testing equality between :a_very_long_symbol_like_this and
:another_very_long_symbol is only comparing their object_ids, basically
two integers.
The property that any future :foo must return the same object_id means
that the Symbol table is never garbage-collected. A Symbol is for life,
not just for Christmas.
Strings are collections of bytes/characters. They can be mutated. There
can be many String objects in the system which contain the same sequence
of bytes/characters. Therefore, comparing two Strings always has to be
done byte-by-byte.(***)
In general, what you want is a String. If you're reading data from a
user (e.g. on STDIN or a web-page POST) then it comes in as a String.
You can convert a String into a Symbol represented by the same set of
characters:
a = "foo"
b = a.intern # b = :foo
but this can be a dangerous thing to do if the string you are converting
came from an untrusted source, because it can lead to a simple
denial-of-service attack as the user floods your symbol table with
garbage.
So to summarise, Symbols are used as method names:
a = 1
b = a.send
+, 2) # b = a + 2
and are often used as hash keys, because the lookup operations are
cheaper.
def doit(params)
puts params[:foo]
puts params[:bar]
end
doit
foo=>123, :bar=>456)
If coming from a language like C, think of symbols more as enums rather
than strings, where the programmer is using an easy-to-read label like
:foo, but the underlying value is actually a number.
HTH,
Brian.
(*) Example from ruby 1.8:NoMethodError: undefined method `size' for :foo:Symbol
from (irb):2
from :0
But:
1.9.2-p0 > :foo.size
=> 3
(**) Everything you say about Strings or Symbols in 1.9 has to be
qualified, because it's such a complex area. Suffice to say, in 1.9 it's
possible to have two distinct Symbols which are labelled by the same
series of bytes but with different encodings.
Things are far simpler in ruby 1.8, where bytes are real bytes, and
small furry creatures from Alpha Centuri are real small furry creates
from Alpha Centuri.
(***) There are in fact some optimisations whereby two distinct string
objects can share the same underlying data buffer, with copy-on-write.
But in general comparing strings needs to compare the buffers.
And even though ruby 1.9 has strings of characters, the comparisons
*are* done byte-by-byte, not character by character.