Getting Over Symbols

G

gwtmp01

When I was first learning Ruby, symbols were a bit of a mystery.
I understand them now, and in hindsight, I don't really understand
why they were so confusing. In teaching other people about Ruby and
in reading ruby-talk it is quite clear that symbols are an early
stumbling block for learning Ruby. I'd take an educated guess that
people learning Rails (or any other Ruby framework) struggle with
trying to understand if symbols are a magic feature of the framework
or the language or something else.

My question to the list is, why? What is it about Symbols that
creates such confusion? I'm getting ready to prepare a two-hour
"Intro to Ruby" seminar and I'd like to find an approach to Symbols
that cuts through the confusion.

One thought that I've had is that Ruby's reflection capabilities
expose the names of various internal structures (classes, methods,
modules, constants) in a way that is quite foreign to many programmers.
For example, in C you don't have any runtime access to the symbol table
so you would never see a value that could be mapped to a function like
'printf', 'scanf', or 'main' unless the programmer took the trouble to
construct an explicit symbol table (mapping strings to function
pointers,
for example). An explicit table isn't much of a mystery.

When you switch to a language like Ruby, Smalltalk, and certainly the
entire family of Lisp languages you are now in an environment where the
data structures of the language runtime are exposed to the programmer.
For a while, the novice will struggle because their mental model of
a runtime environment just doesn't match their new reality and symbols
just happen to be the bridge between the two worlds. One of the first
features of Ruby that many people learn are the 'attr*' methods. Right
off the bat, the novice is exposed to the mappings from strings to
symbols to methods.

Do folks coming from the Lisp/Scheme world have trouble with symbols or
do they absorb symbols right away because they already struggled with
the concept when learning about atoms?

Thoughts?

Gary Wright
 
J

James Edward Gray II

I'd take an educated guess that
people learning Rails (or any other Ruby framework) struggle with
trying to understand if symbols are a magic feature of the framework
or the language or something else.

It's my opinion that Rails complicates this issue quite a bit, with
it's prevalent use of it's HashWithIndifferentAccess. Sadly, I think
this creates more gotchas than it solves. (I'm not trying to bash
Rails here, just making an observation.)
My question to the list is, why? What is it about Symbols that
creates such confusion? I'm getting ready to prepare a two-hour
"Intro to Ruby" seminar and I'd like to find an approach to Symbols
that cuts through the confusion.

I always introduce it as an immutable String. That seems to suck the
magic out of in.

James Edward Gray II
 
D

David A. Black

Hi --

When I was first learning Ruby, symbols were a bit of a mystery.
I understand them now, and in hindsight, I don't really understand
why they were so confusing. In teaching other people about Ruby and
in reading ruby-talk it is quite clear that symbols are an early
stumbling block for learning Ruby. I'd take an educated guess that
people learning Rails (or any other Ruby framework) struggle with
trying to understand if symbols are a magic feature of the framework
or the language or something else.

My question to the list is, why? What is it about Symbols that
creates such confusion? I'm getting ready to prepare a two-hour
"Intro to Ruby" seminar and I'd like to find an approach to Symbols
that cuts through the confusion.

I've seen Symbol confusion in the following forms:

1. Confusion between Symbol objects and symbols in the sense of
identifiers in a Ruby program. This code:

x = 1

may result in :x being put in the symbol table, but the x in that
expression is not a Symbol object. I don't think this distinction is
always clear to people.

2. Overuse of symbols. This kind of thing:

methods.each do |m| something.send(m.intern) end

is almost certainly pointless, in terms of efficiency. I think symbols
have a kind of mystique -- as if there's something sort of sloppy or
substandard or laughably high-level about using strings where you could
use symbols. In fact, the methods that take strings or symbols as
arguments are usually well-engineered to handle either.

3. Over-emphasis on the symbol table and its meaning. Maybe I
under-emphasize it in my own thinking... but I've never seen any practical
reason to think of symbols in terms of a table, even if one exists
internally. I can't call to mind any case where the data structures
involved in the interpreter's handling of symbols would make any
difference to me. All I need to know is that symbols are immediate,
immutable, and fast.

I'm not campaigning against understanding the interpreter. But from the
user side -- which is where we are when we use Ruby -- symbols are still
an abstraction. When I do "send:)meth)", I'm not manipulating the symbol
table *as* a table. The table-ness is an implementation detail. Symbol
objects are part of Ruby.

4. Conflation of symbols and methods. Sort of along the same lines: :meth
is no closer to the method you get when you do method:)meth) than "meth"
is. It may be closer internally, but in practical terms, it isn't. You
can't do: :meth += "2" and change the name of "meth" to "meth2". The
symbol is the ending point, not the starting point.
One thought that I've had is that Ruby's reflection capabilities expose
the names of various internal structures (classes, methods, modules,
constants) in a way that is quite foreign to many programmers. For
example, in C you don't have any runtime access to the symbol table so
you would never see a value that could be mapped to a function like
'printf', 'scanf', or 'main' unless the programmer took the trouble to
construct an explicit symbol table (mapping strings to function
pointers, for example). An explicit table isn't much of a mystery.

To my knowledge there's no programmatic access to the underlying symbol
table in Ruby. (Am I wrong about this? Have I missed all the
table-manipulating fun? :)
When you switch to a language like Ruby, Smalltalk, and certainly the
entire family of Lisp languages you are now in an environment where the
data structures of the language runtime are exposed to the programmer.
For a while, the novice will struggle because their mental model of
a runtime environment just doesn't match their new reality and symbols
just happen to be the bridge between the two worlds. One of the first
features of Ruby that many people learn are the 'attr*' methods. Right
off the bat, the novice is exposed to the mappings from strings to
symbols to methods.

Again, I think that from the programmer's perspective, you can map from
strings to methods just as easily:

attr_reader :a
attr_reader "a"
attr_reader :a.to_s
attr_reader "a".to_sym

Obviously the first one is the common case, and the first two are the only
useful ones. But conceptually, I think of strings and symbols, in such
cases, as equidistant from the underlying method -- except for the hint
that symbols are faster.


David
__
David A. Black
(e-mail address removed)

"Ruby for Rails", forthcoming from Manning Publications, April 2006!
 
R

Ross Bamford

I always introduce it as an immutable String. That seems to suck the
magic out of in.

It took your describing it so before I saw that symbols aren't nearly as
complex as they sound. It's the connotations of the word 'symbol' I
guess...
 
G

gwtmp01

To my knowledge there's no programmatic access to the underlying
symbol
table in Ruby. (Am I wrong about this? Have I missed all the
table-manipulating fun? :)

When you define an instance method you are adding an entry to the
method table for the class. The key for this table is a symbol so
you might be implicitly adding an entry into the internal table
of all symbols (maintained by the Symbol class). When you call
method("puts") or send("puts") you are looking up an entry in the
method table. When you call remove_method("puts") you are deleting
the entry in the method table. Same situation for constants (which
implicitly
means Modules and Classes). This is what I meant by symbol table.
Again, I think that from the programmer's perspective, you can map
from
strings to methods just as easily:

attr_reader :a
attr_reader "a"
attr_reader :a.to_s
attr_reader "a".to_sym

Yes, it is this mapping from strings/symbols to methods that is novel
for many programmers. I think it is the novelty of this built-in
mapping ability that gets confused with the abstract-data-type aspect
of Symbols.
 
D

David A. Black

Hi --

When you define an instance method you are adding an entry to the
method table for the class. The key for this table is a symbol so
you might be implicitly adding an entry into the internal table
of all symbols (maintained by the Symbol class). When you call
method("puts") or send("puts") you are looking up an entry in the
method table. When you call remove_method("puts") you are deleting
the entry in the method table. Same situation for constants (which
implicitly
means Modules and Classes). This is what I meant by symbol table.

I understand -- but what I meant was, there's no situation where you
directly do:

the_symbol_table << :sym, method:)x) # homemade 'alias'

or

the_symbol_table.each_row do { ... }

In other words, you don't address the table as a tabular data structure
programmatically.
Yes, it is this mapping from strings/symbols to methods that is novel
for many programmers. I think it is the novelty of this built-in
mapping ability that gets confused with the abstract-data-type aspect
of Symbols.

I would separate the concerns. The reflection/metaprogramming stuff in
Ruby isn't really about the Symbol class. So you could, as JEG3 suggests,
describe them principally as an immutable (and quickly resolvable) string
variant.


David
__
David A. Black
(e-mail address removed)

"Ruby for Rails", forthcoming from Manning Publications, April 2006!
 
G

gwtmp01

In other words, you don't address the table as a tabular data
structure
programmatically.

Agreed, but in a static language (yes, I know that is a fuzzy
term) even the implicit manipulation that we were both talking
about doesn't exist or is severely limited.
 
K

Kris

Very interesting post to a newbie like me. Coming from a "C" family of
languages, you just broadened my understanding of Ruby. Until now I
failed to see the importance of exposing the runtime data structures of
the language. Java/.NET allow it to some extent with their Reflection
capabilities. Unlike Ruby (and probably Lisp family of languages) the
reflection capablities of these platforms are limited. I guess this is
by design.
 
T

Trans

The : (colon) notation doesn't help eithrr. Given the other prefixes
like @ and @@ and $ my original instinct was to think it was something
like that. Of course, I soon realized it was more like ' or ", but
non-bracketing.

T.
 
L

Levin Alexander

T24gMTIvNC8wNSwgSmFtZXMgRWR3YXJkIEdyYXkgSUkgPGphbWVzQGdyYXlwcm9kdWN0aW9ucy5u
ZXQ+IHdyb3RlOgoKPiBJIGFsd2F5cyBpbnRyb2R1Y2UgaXQgYXMgYW4gaW1tdXRhYmxlIFN0cmlu
Zy4gIFRoYXQgc2VlbXMgdG8gc3VjayB0aGUKPiBtYWdpYyBvdXQgb2YgaW4uCgpJbnRlcmVzdGlu
Zy4gIEkgYWx3YXlzIHRoaW5rIG9mIHRoZW0gYXMgYSBOdW1iZXIgd2l0aCBhbiBhcmJpdHJhcnkg
dmFsdWUuCgogIGZvb1s6YmFyXSA9ICJiYXoiCgppcyBzb21ld2hhdCByZWxhdGVkIHRvOgoKICAj
ZGVmaW5lIEJBUiA9IDEKICBmb29bQkFSXSA9ICJiYXoiCgoKVmllbGUgR3LDvMOfZSwKTGV2aW4K
 
S

Sean O'Halpin

I understand -- but what I meant was, there's no situation where you
directly do:
[snip]

the_symbol_table.each_row do { ... }
Hi David,

No, but you could do Symbols.all_symbols.each do {} ;)

Regards,

Sean
 
B

Brian Schröder

[snip interesting on topic stuff]

as JEG3 suggests,

Ah, have they finally released the new version? Where can I find the change=
log?

cheers,

Brian
[snip]

David
__
David A. Black
(e-mail address removed)

"Ruby for Rails", forthcoming from Manning Publications, April 2006!
 
E

Eero Saynatkari

gwtmp01 said:
When I was first learning Ruby, symbols were a bit of a mystery.
I understand them now, and in hindsight, I don't really understand
why they were so confusing. In teaching other people about Ruby and
in reading ruby-talk it is quite clear that symbols are an early
stumbling block for learning Ruby. I'd take an educated guess that
people learning Rails (or any other Ruby framework) struggle with
trying to understand if symbols are a magic feature of the framework
or the language or something else.

My question to the list is, why? What is it about Symbols that
creates such confusion? I'm getting ready to prepare a two-hour
"Intro to Ruby" seminar and I'd like to find an approach to Symbols
that cuts through the confusion.

The most common confusion I have seen is the mistaken understanding
that Symbols are variables (or references to variables) instead of
values; things like :x = 'foo' and x = 'bar'; quux = :x.

Secondly, there is the occasional issue of confusing them with
pointers, probably because of their use to access methods and
such.

Once the other hurdles are cleared, the difference between Strings
and Symbols is a bit hazy.

One thought that I've had is that Ruby's reflection capabilities
expose the names of various internal structures (classes, methods,
modules, constants) in a way that is quite foreign to many programmers.
For example, in C you don't have any runtime access to the symbol table
so you would never see a value that could be mapped to a function like
'printf', 'scanf', or 'main' unless the programmer took the trouble to
construct an explicit symbol table (mapping strings to function
pointers,
for example). An explicit table isn't much of a mystery.

When you switch to a language like Ruby, Smalltalk, and certainly the
entire family of Lisp languages you are now in an environment where the
data structures of the language runtime are exposed to the programmer.
For a while, the novice will struggle because their mental model of
a runtime environment just doesn't match their new reality and symbols
just happen to be the bridge between the two worlds. One of the first
features of Ruby that many people learn are the 'attr*' methods. Right
off the bat, the novice is exposed to the mappings from strings to
symbols to methods.

Do folks coming from the Lisp/Scheme world have trouble with symbols or
do they absorb symbols right away because they already struggled with
the concept when learning about atoms?

Thoughts?

Gary Wright

E
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,805
Latest member
ClydeHeld1

Latest Threads

Top