Today we're going to review something you've already learned,
but I really want to bring it home.
Characters, Strings and Symbols.
What you will learn is how to handle characters,
how strings are represented,
and what a symbol is in relation to a string.
Let's take it from the start: Characters.
In Pharo, characters start with dollar sign,
followed by a letter.
This is to represent literal characters.
Non-printable characters that do not have a form
use space, tab or carriage return,
which jumps to a new line.
We send a message to this character class
to get this character.
Now for strings.
Strings of characters are delimited by single quotes.
This character right here.
Here we have the string: 'eclair au chocolat'.
It starts here and ends here.
We can send it a message, for example, size.
And it sends back "18".
Indeed, this string contains 18 characters.
We can even play with this string.
I can say character space split.
This means I will cut up this string according to spaces,
and I get an OrderedCollection with 3 elements.
The string was cut up into 3 elements.
Strings of characters are collections like any other in Pharo.
A string is really a collection of characters,
but the string class will inherit from the collection class.
So I can use all of the classic methods.
Remember, we have common collection classes.
For example, "at:" for all the indexed collections.
'eclair au chocolat' at: 1
means I want element "1" of this collection and I get "e".
It corresponds to this "e".
I can also use "do:" which runs through the elements of a collection.
And after every loop, the block setting
equals the first element of the collection, then the second, etc.
One small subtlety.
Since strings of characters are delimited by single quotes,
if I want to put code in a string,
the trick is to use two quotes, side by side.
This means I want to insert one quote into my string of characters...
But be careful, the subtlety is that
it counts as only one element in the string.
For example: 'L''eclair au chocolat' at: 2
means I want element 2 of this collection.
And it sends back the quote character.
And if I ask for at: 3 I get the "e" that is here.
So even if I enter two single quotes, they count as one.
Strings of characters are treated like any other collection.
I can say that I want the last element of a string.
If I ask for "str at: str size" I get the very last element.
Don't forget, in Pharo strings begin with index value 1,
therefore the last element is the size of the string.
Or we can simply use "last" to recover the last element.
To generate strings, there are various techniques.
The easiest one is the conversion method.
I convert a symbol into a string of characters with asString.
Or else I can send printString to any object.
This will give me a string representation of the object.
Or I can generate a creation method directly from a collection.
Remember, you can send “with” to any collection class
to generate a new collection that automatically contains certain objects.
If I use String with: $A,
I get a string that contains one single character: "A."
For concatenation,
you've already seen this, we use the "comma" message.
I send "," to a string and run it through another string
to create a new string that is the concatenation of the two.
Nonetheless, be careful.
If I take the same example, you must understand
that I generated intermediate versions that are useless.
So I have this first message that was sent
to this string, with this value.
We have a first concatenation string that was generated.
This concatenation sent the message "," with this value,
and another string was created: The final result.
An intermediate string we haven't seen was generated,
and it makes you lose time in your calculations.
You had a session on benchmarking.
You can use benchmarking to really see what's going on
and whether it wouldn't be worthwhile to use a stream.
I generate a string of characters
and I say that I will define a streamContent with :s
And I can directly send strings to this stream to generate the final string.
This way, I avoid intermediary strings.
Now for symbols.
Syntactically speaking, symbols start with a hashtag,
then a string of characters.
This is a literal symbol.
It's a kind of string, but be careful, they're unique in the system.
If I write hashtag "blah blah" anywhere in my program,
anywhere else in the program this appears,
I'm designating the same object.
It's the same instance.
So symbols are unique.
Here we have #calvin == #calvin and it sends back true.
It's the same object.
This is not the case for strings. For strings, it depends.
It depends on the compiler's optimizations.
So this is the real difference between symbols and strings.
A symbol is solely in read-only.
Symbols cannot be modified, you must create a new one.
It's a unique object, so it always points to the same object.
Strings are mutable objects, you can modify their content.
It says "for now" because this point is under discussion.
Symbols are often used as
method selectors.
And symbols are good candidates for keys
in dictionaries,
namely identityDictionary.
You remember this?
We compare elements,
and we are easily able to calculate hashes starting with a symbol,
in order to generate it in a dictionary.
The important thing to remember from this session,
is that strings are like any other collection.
And that symbols are unique,
in read-only mode, and immutable.