Next: , Previous: Inside Arrays, Up: Behind the scenes

6.12.2 Two flavors of equality

As first seen in chapter two, Smalltalk keys its dictionary with things like #word, whereas we generally use 'word'. The former, as it turns out, is from class Symbol. The latter is from class String. What's the real difference between a Symbol and a String? To answer the question, we'll use an analogy from C.

In C, if you have a function for comparing strings, you might try to write it:

        streq(char *p, char *q)
            return (p == q);

But clearly this is wrong! The reason is that you can have two copies of a string, each with the same contents but each at its own address. A correct string compare must walk its way through the strings and compare each element.

In Smalltalk, exactly the same issue exists, although the details of manipulating storage addresses are hidden. If we have two Smalltalk strings, both with the same contents, we don't necessarily know if they're at the same storage address. In Smalltalk terms, we don't know if they're the same object.

The Smalltalk dictionary is searched frequently. To speed the search, it would be nice to not have to compare the characters of each element, but only compare the address itself. To do this, you need to have a guarantee that all strings with the same contents are the same object. The String class, created like:

        y := 'Hello'

does not satisfy this. Each time you execute this line, you may well get a new object. But a very similar class, Symbol, will always return the same object:

        y := #Hello

In general, you can use strings for almost all your tasks. If you ever get into a performance-critical function which looks up strings, you can switch to Symbol. It takes longer to create a Symbol, and the memory for a Symbol is never freed (since the class has to keep tabs on it indefinitely to guarantee it continues to return the same object). You can use it, but use it with care.

This tutorial has generally used the strcmp()-ish kind of checks for equality. If you ever need to ask the question “is this the same object?”, you use the == operator instead of =:

        x := y := 'Hello'
        (x = y) printNl
        (x == y) printNl
        y := 'Hel', 'lo'
        (x = y) printNl
        (x == y) printNl
        x := #Hello
        y := #Hello
        (x = y) printNl
        (x == y) printNl

Using C terms, = compares contents like strcmp(). == compares storage addresses, like a pointer comparison.