This post originated from an RSS feed registered with Ruby Buzz
by Christian Neukirchen.
Original Post: Ruby Symbols are not Lisp symbols
Feed Title: chris blogs: Ruby stuff
Feed URL: http://chneukirchen.org/blog/category/ruby.atom
Feed Description: a weblog by christian neukirchen - Ruby stuff
With all the rage for reasons whatsoever about Ruby and its Symbols,
people often start to compare Ruby symbols with Lisp symbols. Don’t
do that, it’s just wrong.
Ruby symbols are not Lisp symbols!
There are at least six important differences:
For Lisp symbols, the Common Lisp Hyperspec
says
(in this post, Lisp is considered to be Common Lisp):
Symbols are used for their object identity to name various entities
in Common Lisp, including (but not limited to) linguistic entities
such as variables and functions.
Symbols can be collected together into packages. A symbol is said to
be interned in a package if it is accessible in that package; the
same symbol can be interned in more than one package. If a symbol is
not interned in any package, it is called uninterned.
About Ruby symbols, ri says:
Symbol objects represent names and some strings inside the Ruby
interpreter. […] The same Symbol object will be created for a
given name or string for the duration of a program’s execution,
regardless of the context or meaning of that name.
This is the first imporant difference: Ruby symbols are globally
unique, Lisp symbols can exist in several packages. This means that
there can be symbols in Lisp which have the same name but are
different: FOO and FOO will always be the same, but a symbol
FOO given in package A to a function in package B will not be equal
to FOO there. This can easily confuse newbies.
Second difference: Lisp symbols can be uninterned, whereas Ruby
symbols only exist when they are interned. (An exercise to the Ruby
curious: Find out how to check if a symbol with given name exists,
without interning it. Answer below.)
Third difference: Lisp symbols carry data, Ruby symbols only identify.
A certain Lisp symbol has two slots, a value cell and a function cell.
Since Common Lisp is a Lisp-2, a symbol therefore can “be” a
variable and a function at the same time. Ruby symbols aren’t
anything, but they can be used to lookup methods (but not local
variables, despite Ruby also being a Lisp-2… and for instance variables,
don’t forget the @).
Fourth difference: Lisp symbols have a property list, Ruby symbols
don’t (but you could add that). Imagine a Lisp property list like
instance variables in Ruby. Property lists often are used to attach
data to symbols (this was used for the first object-oriented
programming styles, a.k.a. “flavours” in Lisp, for example).
Fifth difference: Lisp symbols can get garbage-collected if they are
unbound, Ruby symbols stay alive forever. This can be considered an
implementation detail but has to be kept in mind if you intern a lot
in long running processes. (Don’t!)
Sixth difference: Lisp symbols are upcased automatically by default,
Ruby symbols are created as specified. Basically, foo and FOO is
the same in Lisp, but :foo and :FOO aren’t in Ruby. To create
something like :foo in Lisp, you’d need to write |foo|.
These differences make clear that Lisp symbols are rather different to
Ruby symbols, but there is one “exception”, the Lisp symbols of
package KEYWORD. Now, guess how these Lisp symbols are
created… exactly: with a leading colon. The Lisp symbol :foo
is a symbol called “FOO” in the package “KEYWORD”. Therefore, the
Lisp symbol created given by :foo always is the same as :foo.
Keywords are mainly used for keyword parameters (cf. Rails), where the
calling package often isn’t the definiton package.
I conclude:
Ruby symbols aren’t Lisp symbols, but Lisp keywords.