Trying to understand symbols

Hello!

I don't fully understand symbols in Ruby even if I've read books and
postings here.

Symbols are often compared to strings like the following.

h1 = {:a => 1} #symbol. faster and immutable.
h2 = {'a' => 1}

Ok, I can understand that.
Now, is the term 'symbol' used the same meaning in the following text
(from PickAxe2 page 314)?

<snip>
When Ruby sees a name such as a in an expression, it needs to determine
if it is a local
variable reference or a call to a method with no parameters. To decide
which is the case,
Ruby uses a heuristic. As Ruby parses a source file, it keeps track of
symbols that have
been assigned to. It assumes that these symbols are variables. When it
subsequently
comes across a symbol that could be a variable or a method call, it
checks to see if
it has seen a prior assignment to that symbol. If so, it treats the
symbol as a variable;
otherwise it treats it as a method call. As a somewhat pathological
case of this, consider
the following code fragment, submitted by Clemens Hintze.
</snip>

Before I met Ruby, I regarded 'symbol' as the one in the text.
But Ruby's symbol seems to have its unique meaning and usage.

Can anybody clarify that?

Thanks.

Sam

No, they are not the same. The latter is the general meaning of
symbol in a parser context. The former is a specific type of value in
Ruby.

Jacob Fugal

···

On 7/25/05, Sam Kong <sam.s.kong@gmail.com> wrote:

Symbols are often compared to strings like the following.

h1 = {:a => 1} #symbol. faster and immutable.
h2 = {'a' => 1}

Ok, I can understand that.
Now, is the term 'symbol' used the same meaning in the following text
(from PickAxe2 page 314)?

<snip>
When Ruby sees a name such as a in an expression, it needs to determine
if it is a local variable reference or a call to a method with no parameters. To
decide which is the case, Ruby uses a heuristic. As Ruby parses a source
file, it keeps track of symbols that have been assigned to....
</snip>

You are correct to think these two usages of 'symbol' are conflicting
-- if it helps, in the text you quote from p. 314, replace the word
'symbol' with 'name'.

It's just a mis-match in terminology: in parser/compiler-speak, a
'symbol' is just a type of token, not a special kind of immutable
string like it is in Ruby.

Hope that helps,

Lennon

Hi --

Before I met Ruby, I regarded 'symbol' as the one in the text.
But Ruby's symbol seems to have its unique meaning and usage.
Can anybody clarify that?

A symbol object, like :x, is different from what one might generically
call a symbol. So here:

   sym = :x

sym is a symbol in a generic or general sense, whereas :x is an
instance of class Symbol. When people talk about things like using
symbols as hash keys, they mean instances of Symbol -- :x and things
like that. It's common usage to call things like sym (above) symbols
too, so there's some overloading of the term.

David

···

On Tue, 26 Jul 2005, Sam Kong wrote:

--
David A. Black
dblack@wobblini.net

Thanks, rcoder!

But, what bothers me is the following case.

class Foo
   def foo
     puts "foo"
   end
end

Foo.new.send(:foo)

In this case, :foo is not just a string-like thing.
It seems more like the one in the quoted text.

What do you think?

Sam

Thanks David!

David A. Black wrote:

sym is a symbol in a generic or general sense, whereas :x is an
instance of class Symbol. When people talk about things like using
symbols as hash keys, they mean instances of Symbol -- :x and things
like that. It's common usage to call things like sym (above) symbols
too, so there's some overloading of the term.

Your explanation made it clear!

One more think to clear up.

f.send(:foo) #<- is :foo a symbol like an instance of Symbol or just a
generic symbol?
If :foo is not an instance of Symbol, then ':' is used for 2 kinds of
things in Ruby, right?

Thanks.

Sam

Hi --

Thanks, rcoder!

But, what bothers me is the following case.

class Foo
  def foo
    puts "foo"
  end
end

Foo.new.send(:foo)

In this case, :foo is not just a string-like thing.
It seems more like the one in the quoted text.

What do you think?

The :foo in send(:foo) is just a symbol (instance of Symbol :-). It
has no special status beyond that. It happens to match the name of a
method, but the symbol object has no relation to that method.

send is defined so that it can take a symbol or a string; you could
also do:

   Foo.new.send("foo")

which can be handy when you need to do string interpolation to get the
name of the method.

David

···

On Tue, 26 Jul 2005, Sam Kong wrote:

--
David A. Black
dblack@wobblini.net

In this case, :foo is not just a string-like thing.
It seems more like the one in the quoted text.

In this case, ruby is using an instance of the Symbol class as the
search criterion for finding the method. The 'symbol' in the sense of
the compiler token never comes into play, because the compiler isn't
involved at run time (barring an 'eval' call). The compiler 'symbols'
have already been translated into their ruby internal representations
(ok, I used broad strokes here, bear with me). Send() just uses the
:foo symbol to search the ruby internals for a method with the name
'foo'. BTW, you could have used 'foo' instead of :foo.

Dan

Sam Kong asked:

One more think to clear up.

f.send(:foo) #<- is :foo a symbol like an instance of Symbol or just a
generic symbol?
If :foo is not an instance of Symbol, then ':' is used for 2 kinds of
things in Ruby, right?

:foo is an instance of Symbol

% irb
irb(main):001:0> :foo.is_a? Symbol
=> true

The colon (:slight_smile: prefix is Ruby for a literal Symbol, just like surrounding
something in quotes (" or ') gives a String, or slashes (/) gives a Regexp.

You can of course assign it to a variable like any other object:
  x = :foo
  f.send(x)

A "symbol" in context of the parser, like from your Pickaxe quote, has
nothing to do with programming Ruby, it's just used to denote a name or
identifier. See how the passage you quote starts: "When Ruby sees a name
such as a in an expression" - it's just talking about a word in your code
that looks like a variable name or a method name.

HTH,
Dave

In article <Pine.LNX.4.61.0507251714050.14123@wobblini>,
dblack@wobblini.net says...

The :foo in send(:foo) is just a symbol (instance of Symbol :-). It
has no special status beyond that. It happens to match the name of a
method, but the symbol object has no relation to that method.

Really? Is that always true - a Ruby symbol is essentially a C enum
except that you can't define an int value for it?

So that would mean that Rails's use of symbols (e.g. attr_reader :foo)
is just a convention, and Rails uses the symbol-name to go look up an
Object with the same name, thus appearing to releate the Symbol to the
Object?

···

--
Jay Levitt |
Wellesley, MA | I feel calm. I feel ready. I can only
Faster: jay at jay dot fm | conclude that's because I don't have a
http://www.jay.fm | full grasp of the situation. - Mark Adler

Thanks, Dave!

Dave Burt wrote:

The colon (:slight_smile: prefix is Ruby for a literal Symbol, just like surrounding
something in quotes (" or ') gives a String, or slashes (/) gives a Regexp.

May I think that symbols exist in Ruby becuase Ruby's strings are not
immutable?
Python, Java, and C# don't have symbols as far as I know.
Is it because their strings are immutable?

Thanks.

Sam

Just to be clear, attr_reader :method_name is pure Ruby. It's not a Rails-ism.

James Edward Gray II

···

On Jul 25, 2005, at 10:11 PM, Jay Levitt wrote:

So that would mean that Rails's use of symbols (e.g. attr_reader :foo)

In article <Pine.LNX.4.61.0507251714050.14123@wobblini>,
dblack@wobblini.net says...
> The :foo in send(:foo) is just a symbol (instance of Symbol :-). It
> has no special status beyond that. It happens to match the name of a
> method, but the symbol object has no relation to that method.

Really? Is that always true - a Ruby symbol is essentially a C enum
except that you can't define an int value for it?

Sort of, though they're closer to lisp atoms - immutable strings stored
in a special lookup table. They are convertible to/from strings using
String#to_sym and Symbol#to_s. They do respond to object equality, if
that's what you meant -
a = 'hello';
b = 'hello';
c = a.to_sym;
d = b.to_sym
p [a, b, c, d].map {|i| i.object_id} #=> c and d are the same object

So that would mean that Rails's use of symbols (e.g. attr_reader :foo)
is just a convention, and Rails uses the symbol-name to go look up an
Object with the same name, thus appearing to releate the Symbol to the
Object?

It's a common ruby convention, but yes, attr_reader etc. are just
methods that take Symbol arguments, and could have been written to take
String args instead.

martin

···

Jay Levitt <jay+news@jay.fm> wrote:

You may, but you might not be right. IMO, any comparison of Symbol
to something in Python, Java, and C# is (at best) misguided. Strings
in Ruby are (by default) mutable, but can be made immutable by
freezing them:

    irb(main):001:0> a = "foo"
    => "foo"
    irb(main):002:0> a << "bar"
    => "foobar"
    irb(main):003:0> a.freeze
    => "foobar"
    irb(main):004:0> a << "baz"
    TypeError: can't modify frozen string
            from (irb):4:in `<<'
            from (irb):4

IIRC, this is what Hash does when it gets strings as keys:

    irb(main):005:0> a = Hash[*%w(a b c d)]
    => {"a"=>"b", "c"=>"d"}
    irb(main):006:0> a.keys.each { |k| puts "#{k} frozen? #{k.frozen?}" }
    a frozen? true
    c frozen? true
    => ["a", "c"]

Symbols are immutable, yes, but their primary feature is that they
are constant objects and strings aren't:

    irb(main):016:0> %w(a a a).map {|el| el.freeze.__id__ }
    => [22676608, 22676596, 22676584]
    irb(main):017:0> %w(a a a).map {|el| el.to_sym.__id__ }
    => [3086606, 3086606, 3086606]

The comparison of a symbol to a symbol is always going to be
computationally cheaper than the comparison of a string to a string.

-austin

···

On 7/26/05, Sam Kong <sam.s.kong@gmail.com> wrote:

Thanks, Dave!

Dave Burt wrote:

The colon (:slight_smile: prefix is Ruby for a literal Symbol, just like
surrounding something in quotes (" or ') gives a String, or
slashes (/) gives a Regexp.

May I think that symbols exist in Ruby becuase Ruby's strings are
not immutable? Python, Java, and C# don't have symbols as far as I
know. Is it because their strings are immutable?

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Not really. Strings are used because of their content, immutable or not.
Symbols are used because they uniquely define a single object.

If you know lisp, then we can say that Ruby symbols are like Lisp atoms. If
you don't know Lisp, then learn it first, then we can say that Ruby symbols
are like Lisp atoms. :wink:

···

On Tuesday 26 July 2005 11:36 am, Sam Kong wrote:

May I think that symbols exist in Ruby becuase Ruby's strings are not
immutable?
Python, Java, and C# don't have symbols as far as I know.
Is it because their strings are immutable?

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

In article <XDjFe.44415$s54.40074@pd7tw2no>, martindemello@yahoo.com
says...

> So that would mean that Rails's use of symbols (e.g. attr_reader :foo)
> is just a convention, and Rails uses the symbol-name to go look up an
> Object with the same name, thus appearing to releate the Symbol to the
> Object?

It's a common ruby convention, but yes, attr_reader etc. are just
methods that take Symbol arguments, and could have been written to take
String args instead.

Thanks. I had always assumed that a symbol :foo was somehow a reference
to the var/method/whatever called foo.

···

--
Jay Levitt |
Wellesley, MA | I feel calm. I feel ready. I can only
Faster: jay at jay dot fm | conclude that's because I don't have a
http://www.jay.fm | full grasp of the situation. - Mark Adler

Martin DeMello <martindemello@yahoo.com> writes:

So that would mean that Rails's use of symbols
(e.g. attr_reader :foo) is just a convention, and Rails
uses the symbol-name to go look up an Object with the
same name, thus appearing to releate the Symbol to
the Object?

It's a common ruby convention, but yes, attr_reader
etc. are just methods that take Symbol arguments, and
could have been written to take String args instead.

In fact, they do take string arguments.

   class Foo
     attr_accessor "bar"
   end

   foo = Foo.new
   foo.bar = 123
   foo.bar #=> 123

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

Hi, Jim!

Jim Weirich wrote:

···

On Tuesday 26 July 2005 11:36 am, Sam Kong wrote:
> May I think that symbols exist in Ruby becuase Ruby's strings are not
> immutable?
> Python, Java, and C# don't have symbols as far as I know.
> Is it because their strings are immutable?

Not really. Strings are used because of their content, immutable or not.
Symbols are used because they uniquely define a single object.

If you know lisp, then we can say that Ruby symbols are like Lisp atoms. If
you don't know Lisp, then learn it first, then we can say that Ruby symbols
are like Lisp atoms. :wink:

Yeah. I've been reading 'Hackers and Painters' written by Paul Graham
who thinks Lisp is the best language.
I will check Lisp out some day.
Thanks.

Sam