Pickaxe book questions: Symbols and [] method

Hi list, I’ve got this probably lame questions.

In the Pickaxe book 2nd ed. they talk about the attr_reader and
attr_writer on pages 28 and 29 of the book.

There are these attr_reader (eh, methods?) things, which use symbols
instead of variables, why does Ruby use symbols here, what would be
the problem if one uses the variable names instead? The symbol is
pointing to the variable, but the variable is the handle on the data
(variable value) anyway. Like a symlink pointing to a symlink pointing
to the actual file.

And on page 44 (Containers, Implementing a SongList container)

class SongList
def
@songs[index]
end
end

Why is there this [] method in the class SongList, when one is able to
use the [] method on the songs array anyway? Is this because of the
church of good design, that one must access or change the @songs array
via accessor methods, instead of changing the array directly?

Krekna

Krekna M. wrote:

to the actual file.

attr_reader and its friends are methods in the Module class. The symbols
are arguments to the method that specify the names of the reader methods
to be defined. You could certainly use a variable in the argument list,
just like you can for any other method call, but in that case
attr_reader would use the value of the variable as the method name, not
the variable name itself. That is,

foo = “xxx”
attr_reader foo

defines the “xxx” method, not the “foo” method. Of course this may be
exactly what you want to happen. It’s a common technique in Ruby
metaprogramming.

church of good design, that one must access or change the @songs array
via accessor methods, instead of changing the array directly?

You can’t access @songs outside of the method definition itself, so if
you want to provide a way of indexing it to the users of the class you
must provide a method such as this one.

Hi –

On Fri, 29 Dec 2006, Krekna M. wrote:

to the actual file.
See Tim’s answer. I just wanted to add a nuance: symbols do not point
to variables. If you do:

x = 1
s = :x

there’s no special relation between :x and 1, and no special relation
between s and x.

Internally, Ruby uses :x in a symbol table, indicating that you have a
local variable called x. However, that use of :x has nothing to do
with your use of :x. It’s very similar to integers. If you assign
10 to a variable, and Ruby uses the number 10 somewhere internally,
there’s no direct connection.

Symbols are a way of representing text. That means they can often be
used as method arguments where a method might reasonably be expected
to want some text – such as a method name. But the symbol doesn’t
“know” that there’s a method (or variable) with its name.

David

Krekna M. wrote:

class SongList
def
@songs[index]
end
end

Why is there this [] method in the class SongList, when one is able to
use the [] method on the songs array anyway?

This (alone) allows the consumer of the class to write code like:
p my_song_list[ 3 ]

If you wanted to do what you suggest, you’d need to add code like:
class SongList
attr_reader ‘songs’ # You can use strings too, if you like
end

p my_song_list.songs[ 3 ]

The upside of that is that you immediately get access to all the
methods of the underlying array, such as…
my_song_list.songs.each{ |song| … }
…which the former code (alone) doesn’t make possible.

The downside, though, is that you have this class that’s supposed to be
a list…and then you need to use a property of it to get at the list?
Where does the madness end? Can you imagine if your class design
required users to write code like:
p my_song_list.songs.members.items.all[ 3 ]

I think that’s the rationale behind the method you see. It shows how
you can provide a good-looking interface to your own classes.

local variable called x. However, that use of :x has nothing to do
with your use of :x. It’s very similar to integers. If you assign
10 to a variable, and Ruby uses the number 10 somewhere internally,
there’s no direct connection.

Symbols are a way of representing text. That means they can often be
used as method arguments where a method might reasonably be expected
to want some text – such as a method name. But the symbol doesn’t
“know” that there’s a method (or variable) with its name.

This is good to remember. Symbols aren’t references or strings.

The reason you give attr_reader a symbol is not because the symbol
automatically redirects to the attribute, or that it “knows” anything
about what it’s pointing to. You give attr_reader a symbol because the
attr_reader code needs some representation of the attribute’s name.
Since this is text internal to the program itself, you use a symbol.