What is the difference between :foo and "foo"?

Keep in mind that symbols are immediate values backed by
the global_symbols table (actually global_symbols.tbl and
global_symbols.rev, for the name => id and id => name associations
respectively). Since the lower bits encode information like ID_LOCAL,
ID_INSTANCE, etc., symbol values cannot point to the appropriate entry
in global_symbols the same way VALUEs for normal objects point to RVALUE
slots in the object heaps. [1]

During the mark phase, the stack must be scanned for references to live
objects. It's easy to verify if an unsigned (long) long seems to point
to an object, by seeing if the address falls into the area occupied by
some heap and actually corresponds to a slot. In order to mark symbol entries
in global_symbols, a lookup in global_symbols.rev would be needed for each
word in the stack. I conjecture that this would be relatively expensive, but
there are probably better reasons for the current behavior (it's too late to
read the sources in detail though :)...

[1] Even if those bits were not used, another level of indirection would
be needed due to the way the hash table works.

···

On Thu, Dec 29, 2005 at 07:30:44AM +0900, Jim Weirich wrote:

Jim Weirich wrote:
Why are symbols not garbage collected? Because a symbol represents a
mapping from a string name to a unique object. Anytime in the execution
of the program, if that name is used for a symbol, the original symbol
object must be returned. If the symbol is garbage collected, then a
later reference to the symbol name will return a different object.
That's generally frowned upon (although I don't really see the harm. If
the original symbol was GC'ed, nobody cared what the original object was
anyways. But that's the way it works).

--
Mauricio Fernandez

I think :sym.hash uses the method definition from Kernel (inherited through
Object) and :sym.eql?(:foo) would also reuse the existing definition.

[see C code at the bottom]

So there's seemingly no reason for symbol hashing/comparison not to be
faster than for strings. The benchmarks you linked to, as well as Jim's,
use relatively short strings, but one can exaggerate the effect:

# >> Strings Filling
# >> 5.800000 0.000000 5.800000 ( 6.302649)
# >> Strings Fetching
# >> 3.120000 0.010000 3.130000 ( 3.404679)
# >>
# >> Symbols Filling
# >> 2.120000 0.000000 2.120000 ( 2.326393)
# >> Symbols Fetching
# >> 0.640000 0.000000 0.640000 ( 0.700178)

#!/usr/bin/env ruby

require 'benchmark'

SIZE = 100
N = 10000

RUBY_VERSION # => "1.8.4"

def make_str_keys
  (1..SIZE).collect { |i| "long key" * i}
end

def make_sym_keys(strs)
  strs.collect { |s| s.intern }
end

def populate(keys)
  result = {}
  keys.each_with_index do |k, i|
    result[k] = i
  end
  result
end

def fetch(keys, hash)
  keys.each do |key| hash[key] end
end

strs = make_str_keys
syms = make_sym_keys(strs)

str_hash = populate(strs)
sym_hash = populate(syms)

puts "Strings Filling"
puts Benchmark.measure {
  N.times do
    populate(strs)
  end
}

puts "Strings Fetching"
puts Benchmark.measure {
  N.times do
    fetch(strs, str_hash)
  end
}

puts
puts "Symbols Filling"
puts Benchmark.measure {
  N.times do
    populate(syms)
  end
}

puts "Symbols Fetching"
puts Benchmark.measure {
  N.times do
    fetch(syms, sym_hash)
  end
}

    rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
...

VALUE
rb_obj_id(VALUE obj)
{
    if (SPECIAL_CONST_P(obj)) {
  return LONG2NUM((long)obj);
    }
    return (VALUE)((long)obj|FIXNUM_FLAG);
}

    rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
...

static VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
    if (obj1 == obj2) return Qtrue;
    return Qfalse;
}

···

On Thu, Dec 29, 2005 at 06:51:29AM +0900, ara.t.howard@noaa.gov wrote:

On Thu, 29 Dec 2005, Johannes Friestad wrote:
>That's where the 'can be' part comes in :slight_smile:
>The point is that symbols support quicker lookup by their nature.
>Whether they are quicker in practice will depend on the
>implementation. From the timings you give, it looks like symbol lookup
>is implemented by converting the symbol to a string and doing string
>lookup. Which is obviously not quicker :slight_smile:

i never consider that as an impl - i bet your right though... time for me to
read the source.

--
Mauricio Fernandez

Jim Weirich wrote:

I'm not sure if this helped, or just muddied the water more.

When I first was trying to learn about symbols, attempts to explain their "intentions" (as names of things, for example), rather than to explain what they are, just muddied the water for me. Sure, give me some advice on when and when not to use them, but also, tell me what they are, so I can decide for myself:
- Like a string, but:
- Object-level equality, so :foo.equal?(:foo) and not 'foo'.equal?('foo')
- That means, with strings, if you say 'foo' 5 times in the code, you're creating 5 string objects, whereas with symbols, you're only creating one.
- Share many properties with Fixnum (both being "immediate")-- immutable, no singleton classes, object equality, not picked up by ObjectSpace.each_object...
- Not garbage collected.
- Looks cooler -- by using a different syntax, you can give some visual distinction between your keys and your values, for instance.

(Also, Johannes Friestad's explanation was pretty good, IMO.)

Devin

your test did show symbols being faster on my (linux - 2g cpu, 2g ram) machine
too btw...

but this slightly modified version shows strings being a tiny bit faster:

   harp:~ > cat a.rb
   require 'benchmark'

   n = 2 ** 16
   string_hash, symbol_hash = {}, {}

   Benchmark.bm(10) do |b|
     b.report("string set"){ n.times{|x| string_hash[rand.to_s.freeze] = rand}}
   end
   Benchmark.bm(10) do |b|
     b.report("symbol set"){ n.times{|x| symbol_hash[rand.to_s.intern] = rand}}
   end

   string_keys = string_hash.keys.sort_by{ rand }
   symbol_keys = symbol_hash.keys.sort_by{ rand }

   Benchmark.bm(10) do |b|
     b.report("string get"){ string_keys.each{|k| string_hash[k]}}
   end
   Benchmark.bm(10) do |b|
     b.report("symbol get"){ symbol_keys.each{|k| symbol_hash[k]}}
   end

   harp:~ > ./build/ruby-1.8.4/ruby ./a.rb
                   user system total real
   string set 0.470000 0.000000 0.470000 ( 0.471459)
                   user system total real
   symbol set 0.640000 0.020000 0.660000 ( 0.661556)
                   user system total real
   string get 0.100000 0.000000 0.100000 ( 0.101498)
                   user system total real
   symbol get 0.080000 0.000000 0.080000 ( 0.077205)

i think all we are showing here is that there aren't good reasons for one over
the other. but that's good to i supose - since people certainly seem to have
preferences.

cheers.

-a

···

On Thu, 29 Dec 2005, Johannes Friestad wrote:

BTW: Ruby version 1.8.2, Win XP Pro, Pentium M 2.0 GHz

--

ara [dot] t [dot] howard [at] noaa [dot] gov
all happiness comes from the desire for others to be happy. all misery
comes from the desire for oneself to be happy.
-- bodhicaryavatara

===============================================================================

Thank you.

···

On Fri, Dec 30, 2005 at 02:09:40AM +0900, Edward Faulkner wrote:

On Fri, Dec 30, 2005 at 01:50:14AM +0900, Chad Perrin wrote:
> If you tell me that Ruby symbols are basically just Lisp symbols,
> implemented in an OOP way by way of a symbol class, I think I could
> probably come up with a succinct and clear explanation of what a Ruby
> symbol is that would remove a lot of the ambiguity, but so far I still
> don't know if that's what a Ruby symbol actually is.

Yes, I think Ruby symbols and Lisp symbols are the same thing. The
issue is just slightly obscured because Ruby glosses over the Lisp
concept of "quote" by building the quote syntax directly into the
symbol-literal syntax. :mysymbol means the same thing as Lisp's
'mysymbol, except the whole thing is treated as a single literal
token, instead of parsing to (quote mysymbol).

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

print substr("Just another Perl hacker", 0, -2);

Chad Perrin <perrin@apotheon.com> writes:

> If that's the case, what's up with all this tripe about "a symbol is
> just a name" and so on?

Because it's true? Because there are people who don't have lisp
background who are not familiar with what symbol is? Because there are
people who thinks symbols are magical thingie?

It's not really true, though, considering what a symbol is (according to
my current understanding). A symbol is an element of a hash table that
is often used as a name, and it is an (anonymous? not sure how to
qualify that) object. Calling it a "name" seems to be confusing common
use with actual nature, or premature explanation of an abstract way of
thinking about it, depending on how you mean "it is a name" when you say
it. Either way, it seems to be getting the cart before the horse.

> I think these analogies are doing a disservice to people trying to
> get a read on what a symbol is in Ruby.

This is true for all analogies. Different people are receptive to
different analogies. This simply means you are not receptive to the
analogy I made.

I think it's probably more useful to start by describing the actual
functional nature of a symbol, then start in with the analogies if that
doesn't make a lightbulb go on in the person's head.

> people are full of analogies and categorical statements
> that don't really explain anything

The basic message has always been clear: symbol is a mean for you, the
programmer, to name/identify entities. But somehow, people are having
difficulty understanding this and asked for more explanations. This is
when analogies and categorical statements came in.

"A means for you, the programmer, to name/identify entities" is not a
description of what a symbol *is* so much as a description of how you
can use it. It seems awfully odd to me that everything else in the
language tends to get described in terms of what it actually is under
the hood, then starts getting analogies only if the target of the
explanation doesn't get it, while for some reason nobody starts an
explanation of symbols that way in Ruby.

For example: while saying that a method is "a verb" does help one to
"get" how verbs are used in the language, nobody really knows what a
method is until it's explained that it's a mini-algorithm whose
definition is part of a class definition, accessible by way of instances
thereof. As such, someone always starts explaining what a method is
under the hood pretty quickly when trying to get the point of a method
across in teaching OOP. With symbols, though, I keep seeing bland
assertions that a symbol is "just a name", or "a name that is an
object", or something like that, without any explanation of what a
symbol actually does behind the scenes.

I seem to have missed the blog post that mentioned the relationship to
Lisp methods, but even that didn't really address the matter as clearly
as I would have expected.

> While you're at it, define "identifier" within this context.

To help people understanding the meaning of 'identifier', I've been
mentioning it together with 'name': 'name/identify' as in "It is just
a way to name/identify things".

In any case, there is only one definition of identifier so context
should not influence the meaning of it:

>From WordNet (r) 2.0 (August 2003) [wn]:

  identifier
      n : a symbol that establishes the identity of the one bearing it

. . . which, unfortunately, in no way explains what one does with a
"symbol" in a programming context in a helpful way.

A symbol is an element (or a reference to an element, though I hesitate
to use the term "reference" with its programming contextual baggage) in
a hash table. A hash table is, in short, a list maintained "by the
language" rather than by the user. From the programmer's point of view,
this list essentially has only values, not keys, though from the
language's point of view it most certainly has keys. This is primarily
useful for applying names to things, thus the common assertion that "a
symbol is a name".

Is that close, or have I missed something?

···

On Fri, Dec 30, 2005 at 05:07:35AM +0900, Yohanes Santoso wrote:

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

"A script is what you give the actors. A program
is what you give the audience." - Larry Wall

A symbol in Ruby is similar to a symbol in Lisp in that the symbol is a
name, or more precisely a named atom which can also respond to a
request to expose itself as a number (to_i) or a string (to_s). In this
case a Ruby symbol is similar to a Lisp keyword symbol (which is also
prefixed by a colon (:), at least in some versions of Lisp). However,
in Lisp a symbol has much greater functionality. For example, a Lisp
symbol can also be bound to a value, a property list, or a function.

In briefest, my understanding of symbol in Ruby is that it is an
interned string used as a name ("interned" meaning that it is entered
into memory as a single, atomic entity, a monad - there is just one of
it, with a single pointer to it).

I can understand this as a possible implementation, but I
really wonder about the follow-on statement that I've seen,
saying that this can cause memory leaks. If I define a
string and then discard it, shouldn't it be GCed?

-r

···

At 11:31 AM +0900 12/29/05, Devin Mullins wrote:

- That means, with strings, if you say 'foo' 5 times in the code, you're
creating 5 string objects, whereas with symbols, you're only creating one.

--
email: rdm@cfcl.com; phone: +1 650-873-7841
http://www.cfcl.com - Canta Forda Computer Laboratory
http://www.cfcl.com/Meta - The FreeBSD Browser, Meta Project, etc.

Devin Mullins wrote:

When I first was trying to learn about symbols, attempts to explain their "intentions" (as names of things, for example), rather than to explain what they are, just muddied the water for me. Sure, give me some advice on when and when not to use them, but also, tell me what they are, so I can decide for myself:
- Like a string, but:
- Object-level equality, so :foo.equal?(:foo) and not 'foo'.equal?('foo')
- That means, with strings, if you say 'foo' 5 times in the code, you're creating 5 string objects, whereas with symbols, you're only creating one.
- Share many properties with Fixnum (both being "immediate")-- immutable, no singleton classes, object equality, not picked up by ObjectSpace.each_object...
- Not garbage collected.
- Looks cooler -- by using a different syntax, you can give some visual distinction between your keys and your values, for instance.

- Lacking all those cool String methods like #gsub and #

so... nothing like a string.

Yeah, I dunno, the "some named thing" was just a little iffy. The PickAxe was especially annoying in this respect by trying to imply that a symbol was the name of a method, variable, or class, specifically. Maybe I'm just ranting about that.

Sorry for the mess,
Devin

ara wrote:

but this slightly modified version shows strings being a tiny bit
faster:

The difference is that your version measures more than just hash access
speed. It also includes string and symbol creation times. In
particular, to create a symbol, you must first create a string, so you
have twice as many object creations when using symbols.

···

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

> Chad Perrin <perrin@apotheon.com> writes:
>
> > If that's the case, what's up with all this tripe about "a symbol is
> > just a name" and so on?
>
> Because it's true? Because there are people who don't have lisp
> background who are not familiar with what symbol is? Because there are
> people who thinks symbols are magical thingie?

It's not really true, though, considering what a symbol is (according to
my current understanding). A symbol is an element of a hash table that
is often used as a name, and it is an (anonymous? not sure how to
qualify that) object. Calling it a "name" seems to be confusing common
use with actual nature, or premature explanation of an abstract way of
thinking about it, depending on how you mean "it is a name" when you say
it. Either way, it seems to be getting the cart before the horse.

Nope, Symbols have nothing to do with Hashes. They are often used
as Hash keys because they are descriptive: h[:foo] is better than
h[1] if one wants to convey some meaning with the key. In other
languages, you might use a string instead of a Symbol (and you
can, of course, do so in ruby as well: h['foo']).

> > I think these analogies are doing a disservice to people trying to
> > get a read on what a symbol is in Ruby.
>
> This is true for all analogies. Different people are receptive to
> different analogies. This simply means you are not receptive to the
> analogy I made.

I think it's probably more useful to start by describing the actual
functional nature of a symbol, then start in with the analogies if that
doesn't make a lightbulb go on in the person's head.

>
> > people are full of analogies and categorical statements
> > that don't really explain anything
>
> The basic message has always been clear: symbol is a mean for you, the
> programmer, to name/identify entities. But somehow, people are having
> difficulty understanding this and asked for more explanations. This is
> when analogies and categorical statements came in.

"A means for you, the programmer, to name/identify entities" is not a
description of what a symbol *is* so much as a description of how you
can use it. It seems awfully odd to me that everything else in the
language tends to get described in terms of what it actually is under
the hood, then starts getting analogies only if the target of the
explanation doesn't get it, while for some reason nobody starts an
explanation of symbols that way in Ruby.

For example: while saying that a method is "a verb" does help one to
"get" how verbs are used in the language, nobody really knows what a
method is until it's explained that it's a mini-algorithm whose
definition is part of a class definition, accessible by way of instances
thereof. As such, someone always starts explaining what a method is
under the hood pretty quickly when trying to get the point of a method
across in teaching OOP. With symbols, though, I keep seeing bland
assertions that a symbol is "just a name", or "a name that is an
object", or something like that, without any explanation of what a
symbol actually does behind the scenes.

I seem to have missed the blog post that mentioned the relationship to
Lisp methods, but even that didn't really address the matter as clearly
as I would have expected.

>
> > While you're at it, define "identifier" within this context.
>
> To help people understanding the meaning of 'identifier', I've been
> mentioning it together with 'name': 'name/identify' as in "It is just
> a way to name/identify things".
>
> In any case, there is only one definition of identifier so context
> should not influence the meaning of it:
>
> >From WordNet (r) 2.0 (August 2003) [wn]:
>
> identifier
> n : a symbol that establishes the identity of the one bearing it

. . . which, unfortunately, in no way explains what one does with a
"symbol" in a programming context in a helpful way.

A symbol is an element (or a reference to an element, though I hesitate
to use the term "reference" with its programming contextual baggage) in
a hash table. A hash table is, in short, a list maintained "by the
language" rather than by the user. From the programmer's point of view,
this list essentially has only values, not keys, though from the
language's point of view it most certainly has keys. This is primarily
useful for applying names to things, thus the common assertion that "a
symbol is a name".

Is that close, or have I missed something?

E

···

On 2005.12.30 09:36, Chad Perrin <perrin@apotheon.com> wrote:

On Fri, Dec 30, 2005 at 05:07:35AM +0900, Yohanes Santoso wrote:

Chad Perrin <perrin@apotheon.com> writes:

Chad Perrin <perrin@apotheon.com> writes:

> If that's the case, what's up with all this tripe about "a symbol is
> just a name" and so on?

Because it's true? Because there are people who don't have lisp
background who are not familiar with what symbol is? Because there are
people who thinks symbols are magical thingie?

Calling it a "name" seems to be confusing common use with actual
nature, or premature explanation of an abstract way of thinking
about it, depending on how you mean "it is a name" when you say it.

Well, what can I say? Symbol is really meant to represent a
name/identifier.

Let's stop with analogies since obviously we are not
analogy-compatible, and get on with the concretes.

What is 1? A way to represent the number one. You said a way, what
others are there? 0x1, \001, "1". However, one does not use "1" to
represent the number one even if one doesn't plan to do any arithmetic
operations on that number because that representation is
ambiguous. Does he mean "1" as in number one or as in the character
"1"?

What is :server? A way to represent the name/identifier
``server``. What others are there? "server" is another one. But it is
also ambigious. Does he mean the name/identifier ``server`` or the
character sequence "s","e","r","v","e","r"?

I can see no way to describe 1 without involving number. Similarly, I
can see no way to describe :server without involving
name/identifier. Perhaps you can.

"A means for you, the programmer, to name/identify entities" is not a
description of what a symbol *is* so much as a description of how you
can use it.

I really am not sure what you are saying there. That sentence
describes what a symbol is. That sentence does not describe/prescribe
how to use it.

Here, let me paraphrase my sentence: "[Symbol is] a means for you, the
programmer, to [represent the] name/identit[y] of entities". Did I
manage to preserve the meaning? Let's do word substitution. "Number
is a means for you, the programmer, to represent numbers". In no way
am I describing/prescribing how to use instances of Number.

object", or something like that, without any explanation of what a
symbol actually does behind the scenes.

This is precisely the kind of explanation that I objected when
explaining what a symbol is to a newcomer. Any explanation that refer
to the implementation is doomed to be short-lived. There are many ways
to implement the class Symbol and the concept of symbol.

Do you explain what number does behind the scenes to someone asking
'What is a number?' Do you explain that ruby maps number less than
2^31-1 directly to native integer format? Quick question, then: does
this still hold on a 64-bit machine? How about in ruby 2.0? Will
Number behave differently and is used to represent different thing
there simply because what goes on behind the scene has changed?

If one is interested in how something is implemented in a specific
environment, one should ask for that (and there are posts in this
thread dwelving into how Symbol is implemented in current ruby VM).

In any case, if someone can give me a description of what 1 is without
involving number, then I'll show you a description of what symbol is
without involving name/identifier.

YS.

···

On Fri, Dec 30, 2005 at 05:07:35AM +0900, Yohanes Santoso wrote:

And now you have identified the crux of all the misunderstanding (and I think
"misunderstanding" is the right word, given that tens of people smarter than
me disagree with each other on how to describe a symbol).

Long time Rubyists, people with heavy CS studies, and people who have
experience in languages with symbols (LISP, I guess) tend to talk more about
how it's implemented, while programmers (probably without CS degrees)
migrating from languages not containing symbols are more interested in what
it does than how it's implemented.

I asked if it's an object with 2 attributes, an integer key and a string
value. Someone says no, it's an object with one attribute that can be seen 2
ways, a string or an integer. From my point of view, he's saying the same
thing. I was describing what it can do for me, he was describing something
truer to the implementation, but when actually using the little bugger either
explanation will lead to correct programming, at least if I understand it
correctly (and I think I now understand it correctly, at least correctly
enough to know how and when to use a symbol).

One thing I know for sure -- the length and bredth of this thread indicates
for sure that Ruby symbols need much better documentation. Austin Ziegler has
made an excellent start. I volunteer to give input from an imigrant from Perl
land (and C, C++, and about a dozen others but not lisp) whose BS degree is
in Electrical Engineering and whose computer programming classes were limited
to the very practical stuff they taught at Santa Monica Community College.

SteveT

Steve Litt

slitt@troubleshooters.com

···

On Thursday 29 December 2005 07:36 pm, Chad Perrin wrote:

On Fri, Dec 30, 2005 at 05:07:35AM +0900, Yohanes Santoso wrote:
> Chad Perrin <perrin@apotheon.com> writes:
> > If that's the case, what's up with all this tripe about "a symbol is
> > just a name" and so on?
>
> Because it's true? Because there are people who don't have lisp
> background who are not familiar with what symbol is? Because there are
> people who thinks symbols are magical thingie?

It's not really true, though, considering what a symbol is (according to
my current understanding). A symbol is an element of a hash table that
is often used as a name, and it is an (anonymous? not sure how to
qualify that) object. Calling it a "name" seems to be confusing common
use with actual nature, or premature explanation of an abstract way of
thinking about it, depending on how you mean "it is a name" when you say
it. Either way, it seems to be getting the cart before the horse.

Oh, so many replies to my poor question! What a wonderful community!

This version (I believe) shows that by using a string literal, you're
paying for the creation of a string object with each invocation, whereas
by using a symbol, you only pay for the interning once, but on each
subsequent usage, you're using a reference to a singleton.

slyphon@willie ~ $ cat /tmp/bmrk.rb
#!/usr/bin/env ruby

require 'benchmark'

n = 1_000_000
string_hash, symbol_hash = {}, {}

Benchmark.bm(10) do |b|
   b.report("string set"){ n.times{|x| string_hash["foo"] = rand}}
end
Benchmark.bm(10) do |b|
   b.report("symbol set"){ n.times{|x| symbol_hash[:foo] = rand}}
end

slyphon@willie ~ $ ruby /tmp/bmrk.rb
                 user system total real
string set 1.270000 0.000000 1.270000 ( 1.274019)
                 user system total real
symbol set 0.880000 0.000000 0.880000 ( 0.877080)
slyphon@willie ~ $

- Jonathan Simms

···

On Dec 29, 2005, at 12:22 AM, Jim Weirich wrote:

ara wrote:

but this slightly modified version shows strings being a tiny bit
faster:

The difference is that your version measures more than just hash access
speed. It also includes string and symbol creation times. In
particular, to create a symbol, you must first create a string, so you
have twice as many object creations when using symbols.

Apparently, a more significant distinction needs to be made between a
"hash table" in the symbol sense of the term and a "hash" in the sense
of an associative array.

···

On Fri, Dec 30, 2005 at 10:42:33AM +0900, Eero Saynatkari wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 2005.12.30 09:36, Chad Perrin <perrin@apotheon.com> wrote:
>
> It's not really true, though, considering what a symbol is (according to
> my current understanding). A symbol is an element of a hash table that
> is often used as a name, and it is an (anonymous? not sure how to
> qualify that) object. Calling it a "name" seems to be confusing common
> use with actual nature, or premature explanation of an abstract way of
> thinking about it, depending on how you mean "it is a name" when you say
> it. Either way, it seems to be getting the cart before the horse.

Nope, Symbols have nothing to do with Hashes. They are often used
as Hash keys because they are descriptive: h[:foo] is better than
h[1] if one wants to convey some meaning with the key. In other
languages, you might use a string instead of a Symbol (and you
can, of course, do so in ruby as well: h['foo']).

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

unix virus: If you're using a unixlike OS, please forward
this to 20 others and erase your system partition.

For the heck of it, I decided to come up with my own Symbol analogy. Caveat reader:

A symbol is a bubble. In Ruby-land, there is this ever-present *ether* wherein lies an abundance of bubbles.

<picture of a bunch of bubbles, each with a symbol literal inside -- feel free to Gimp it into existence -- here's a starter kit: http://www.scrapbookerie.com/images/autocollants/Sticko-Bubbles.jpg>

Every symbol you could ever want is out there, in the ether, bubbling along. For every name, there is a single bubble. For every bubble, there is a single name.

When you assign +x = :mr_t+, as with all variable assignments, you're pointing x to the :mr_t object. Here, you're pointing at that bubble that the Ruby interpreter recognizes as :mr_t. For plausability reasons, the Ruby interpreter blows the :mr_t bubble the first time you mention its name, but for your sake, you can assume that the :mr_t bubble has always existed and always will exist -- it's just there, floating in the ether, waiting to be pointed to.

So from that description right there, we already know one thing we can do with bubbles--er, Symbols--determine equality. Are these two variables pointing to the same bubble? Find me the Hash value whose associated key is this bubble I'm pointing to right now. For programming convenience, these bubbles have names associated with them, but as far as your code is concerned, they're just bubbles. This is the magic behind {:server => 'localhost', :port => 80}, etc.

The other (principal) thing you can do with a bubble--eh, Symbol--is find out its name at runtime (thanks to #to_s or #id2name). Thus, attr_accessor :mcklellan is born. I'm passing along a pointer to the :mcklellan bubble. attr_accessor follows the pointer, talks to that bubble, asks it what its name is, and uses that information to define some methods. Here, :mcklellan is just used as a fancy shorthand for 'mcklellan'. (It happens to be one I like, but I digress...)

So, uh, yeah. That's it. The End.

Ha, yeah, so that description is probably more unsettling than settling, but maybe it'll plant a seed of wisdom, or whatnot. Plus, I can rest easy, now that I've solved everybody's problems.

Devin
Did I really just digress into "The End"?

Chad Perrin <perrin@apotheon.com> writes:

What is 1? A way to represent the number one. You said a way, what
others are there? 0x1, \001, "1". However, one does not use "1" to
represent the number one even if one doesn't plan to do any arithmetic
operations on that number because that representation is
ambiguous. Does he mean "1" as in number one or as in the character
"1"?

Then why not simply say:

    :symbol is to "symbol" as 1 is to "1"

That would get the point across far more clearly than saying "A symbol
is just a name," especially since strings can be names (from another
perspective), and since variables are "names" in another sense of the
term, and so on. Saying it's "a name" doesn't explain jack, as far as I
can tell.

Being vague doesn't help.

> "A means for you, the programmer, to name/identify entities" is not a
> description of what a symbol *is* so much as a description of how you
> can use it.

I really am not sure what you are saying there. That sentence
describes what a symbol is. That sentence does not describe/prescribe
how to use it.

Let's take a look at that sentence's structure and meaning:

    A [something] is a means [. . .] to [do something].

Gee, looks like a description of how one uses it. A symbol is a means
to name/identify entities. A screwdriver is a means to turn screws. A
mug is a means to transport coffee. By the same token, however,
telekinesis is a means to turn screws, as is a centrifuge if you really
want to put screws into one, for some definition of "turn". Also, a
hose, a Folger's can, and an eighteen wheeler might be a means for
transporting coffee. It's vague and, ultimately, useless for getting
the point across, that point being: What *is* it?

A screwdriver is a handle affixed to a metal shaft with a bit on the end
that serves as the interface for the screw -- the torque point, if you
will. A mug is a drinking vessel that is ideally suited to beverages
such as coffee, allow you to transport the hot beverage from the coffee
pot to your lips after it has been prepared and poured.

For someone who doesn't already know what a mug or screwdriver actually
is, the mere description of what each is a means to do is far too vague
to actually impart much understanding.

> object", or something like that, without any explanation of what a
> symbol actually does behind the scenes.

This is precisely the kind of explanation that I objected when
explaining what a symbol is to a newcomer. Any explanation that refer
to the implementation is doomed to be short-lived. There are many ways
to implement the class Symbol and the concept of symbol.

It may be doomed to be short lived, but without some kind of example
that is recognizable, the prospective student is more likely than not to
learn very little of anything.

Do you explain what number does behind the scenes to someone asking
'What is a number?' Do you explain that ruby maps number less than
2^31-1 directly to native integer format? Quick question, then: does
this still hold on a 64-bit machine? How about in ruby 2.0? Will
Number behave differently and is used to represent different thing
there simply because what goes on behind the scene has changed?

Unlike symbols, numbers are pretty well understood, particularly for
someone coming from another programming language (any language except
the original, archetypal "lisp", pre-implementation, involves numbers).
Symbols are another matter entirely.

The problem with most of the descriptions of symbols I've seen is that
they try to define symbols in terms of themselves to people who don't
already understand those terms. A framistan is a thing. Whee. That
taught me nothin'.

This approach to explaining symbols is equivalent to trying to teach
object oriented programming with nothing more than the statement that
"an object is a thing". Okay, great. What kind of thing? What are all
these terms like "method/message" and "class" and "instance" and so on?
There are entire college courses devoted (almost) solely to imparting a
rudimentary understanding of what an "object" is and how it is used.
Why can't someone come up with a better explanation of a symbol than the
five-word sentences that are so common here?

···

On Fri, Dec 30, 2005 at 02:10:09PM +0900, Yohanes Santoso wrote:

--
Chad Perrin [ CCD CopyWrite | http://ccd.apotheon.org ]

"Real ugliness is not harsh-looking syntax, but having to
build programs out of the wrong concepts." - Paul Graham

Long time Rubyists, people with heavy CS studies, and people who have
experience in languages with symbols (LISP, I guess) tend to talk more
about how it's implemented, while programmers (probably without CS
degrees) migrating from languages not containing symbols are more
interested in what it does than how it's implemented.

And what I've been trying to get across, Steve, is that Symbols don't
actually *do* anything. Nothing. Zero. Zip. ABSOLUTELY NADA! They're
names with the special property that the name uniquely identifies the
object. :wilbur always identifies :wilbur.

I asked if it's an object with 2 attributes, an integer key and a
string value. Someone says no, it's an object with one attribute that
can be seen 2 ways, a string or an integer. From my point of view,
he's saying the same thing.

Then you didn't understand the answer if you saw them as the same. What
I said (rephrasing; I'm too lazy to look up what I really said) is
essentially that a Symbol has one value: itself. If you will, its name.

  puts :wilbur.inspect # => :wilbur

You can *convert* a Symbol to a string:

  puts :wilbur.to_s # => wilbur

You can *convert* a Symbol to an integer value:

  puts :wilbur.to_i # => 23569 !! This value can change !!

But both #to_s and #to_i are conversions, not attributes of the Symbol.
The Symbol's only attribute is ... itself. Just like a Fixnum's only
attribute is ... itself.

  puts 1.inspect # => 1

Look at what Symbol.instance_methods(false) returns:

  ["inspect", "to_int", "===", "to_s", "to_sym", "to_i", "id2name"]

Symbol doesn't otherwise provide any methods not provided by Object (or
Kernel), and most of those listed above are conversion methods.

[...]

Hopefully that's a bit clearer. It's not that different from Perl
barewords.

-austin

···

On 30/12/05, Steve Litt <slitt@earthlink.net> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Steve Litt wrote:

Long time Rubyists, people with heavy CS studies, and people who have
experience in languages with symbols (LISP, I guess) tend to talk more about
how it's implemented, while programmers (probably without CS degrees)
migrating from languages not containing symbols are more interested in what
it does than how it's implemented.

I asked if it's an object with 2 attributes, an integer key and a string
value. Someone says no, it's an object with one attribute that can be seen 2
ways, a string or an integer. From my point of view, he's saying the same
thing. I was describing what it can do for me, he was describing something
truer to the implementation, but when actually using the little bugger either
explanation will lead to correct programming, at least if I understand it
correctly (and I think I now understand it correctly, at least correctly
enough to know how and when to use a symbol).

I'm somewhat new to ruby, and for me it has made most sense to do an ri
on Symbol to check out the api. When I first ran across symbols in the
Pickaxe it didn't make much sense. I started out just taking it on
blind faith how they get used in different frameworks api's. Seems
like what symbols are is different from how they might be best used.
Here's something I wrote up to play around with how they work. I was
surprized to find out that any identifier (class, method, variable,
etc) in a ruby script gets turned into a symbol.

Bill

# Definition: A symbol is an object of class Symbol. The symbol
# has only one instance with given name that can be found by
# calling the method id2name or to_s. The symbol has a unique
# integer value that can be found by calling the to_i method.
# The Symbol class method all_symbols will give an array of all
# symbols. A symbol is automatically generated for any
# identifier used or seen within a ruby program including
# constants, classes, methods, variables, etc. Once a symbol is
# created it is never garbage collected.

def find_and_display_symbol(symbol_name)
  found_symbol = Symbol.all_symbols.find { |s| s.to_s == symbol_name }
  if (found_symbol != nil)
    puts "symbol found with name: #{found_symbol.to_s} and " +
         "id: #{found_symbol.to_i}\n\n"
  else
    puts "unable to find symbol #{symbol_name}\n\n"
  end
end

# create a symbol object called symbol_name
:my_new_symbol

# display the newly created symbol by going through all symbols
# see find_and_display_symbol function below
find_and_display_symbol('my_new_symbol')

# symbols apparently don't have to be a legal identifier
:"Hello World!"
find_and_display_symbol("Hello World!")

#local variable creates a symbol
silly_local_variable = "Hello"
find_and_display_symbol('silly_local_variable')

# Any referenced identifier will create a symbol, even if the symbol is
# undefined:
defined? undefined_variable
find_and_display_symbol('undefined_variable')

# Symbols already exist for builtin classes and methods
find_and_display_symbol('String')
find_and_display_symbol('each')
find_and_display_symbol('$LOAD_PATH')

# list all symbols
sym_array = Symbol.all_symbols
sym_array.sort! {|a,b| a.to_s <=> b.to_s }
sym_array.each {|s| puts "name: #{s.to_s} id: #{s.to_i}\n" }