Character Comparisons
The main thing you can do with characters, other than putting them into strings (which I'll get to later in this chapter), is to compare them with other characters. Since characters aren't numbers, you can't use the numeric comparison functions, such as < and >. Instead, two sets of functions provide character-specific analogs to the numeric comparators; one set is case-sensitive and the other case-insensitive.
The case-sensitive analog to the numeric = is the function CHAR=. Like =, CHAR= can take any number of arguments and returns true only if they're all the same character. The case- insensitive version is CHAR-EQUAL.
The rest of the character comparators follow this same naming scheme: the case-sensitive comparators are named by prepending the analogous numeric comparator with CHAR; the case-insensitive versions spell out the comparator name, separated from the CHAR with a hyphen. Note, however, that <= and >= are "spelled out" with the logical equivalents NOT-GREATERP and NOT-LESSP rather than the more verbose LESSP-OR-EQUALP and GREATERP-OR-EQUALP. Like their numeric counterparts, all these functions can take one or more arguments. Table 10-1 summarizes the relation between the numeric and character comparison functions.
Table 10-1. Character Comparison Functions
| Numeric Analog | Case-Sensitive | Case-Insensitive |
= |
CHAR= |
CHAR-EQUAL |
/= |
CHAR/= |
CHAR-NOT-EQUAL |
< |
CHAR< |
CHAR-LESSP |
> |
CHAR> |
CHAR-GREATERP |
<= |
CHAR<= |
CHAR-NOT-GREATERP |
>= |
CHAR>= |
CHAR-NOT-LESSP |
among other things, testing whether given character is alphabetic or a digit character, testing the case of a character, obtaining a corresponding character in a different case, and translating between numeric values representing character codes and actual character objects. Again, for complete details, see your favorite Common Lisp reference.
Strings
As mentioned earlier, strings in Common Lisp are really a composite data type, namely, a one-dimensional array of characters. Consequently, I'll cover many of the things you can do with strings in the next chapter when I discuss the many functions for manipulating sequences, of which strings are just one type. But strings also have their own literal syntax and a library of functions for performing string-specific operations. I'll discuss these aspects of strings in this chapter and leave the others for Chapter 11.
As you've seen, literal strings are written enclosed in double quotes. You can include any character supported by the character set in a literal string except double quote (") and backslash (\). And you can include these two as well if you escape them with a backslash. In fact, backslash always escapes the next character, whatever it is, though this isn't necessary for any character except for " and itself. Table 10-2 shows how various literal strings will be read by the Lisp reader.
Table 10-2. Literal Strings
| Literal | Contents | Comment |
"foobar" |
foobar | Plain string. |
"foo\"bar" |
foo"bar | The backslash escapes quote. |
"foo\\bar" |
foo\bar | The first backslash escapes second backslash. |
"\"foobar\"" |
"foobar" | The backslashes escape quotes. |
"foo\bar" |
foobar | The backslash "escapes" b |
Note that the REPL will ordinarily print strings in readable form, adding the enclosing quotation marks and any necessary escaping backslashes, so if you want to see the actual contents of a string, you need to use function such as FORMAT designed to print human-readable output. For example, here's what you see if you type a string containing an embedded quotation mark at the REPL:
CL-USER> "foo\"bar"
"foo\"bar"
FORMAT, on the other hand, will show you the actual string contents:[118]
CL-USER> (format t "foo\"bar")
foo"bar
NIL
String Comparisons
You can compare strings using a set of functions that follow the same naming convention as the character comparison functions except with STRING as the prefix rather than CHAR (see Table 10-3).
Table 10-3. String Comparison Functions
| Numeric Analog | Case-Sensitive | Case-Insensitive |
= |
STRING= |
STRING-EQUAL |
/= |
STRING/= |
STRING-NOT-EQUAL |
< |
STRING< |
STRING-LESSP |
> |
STRING> |
STRING-GREATERP |
<= |
STRING<= |
STRING-NOT-GREATERP |
>= |
STRING>= |
STRING-NOT-LESSP |
118
Note, however, that not all literal strings can be printed by passing them as the second argument to FORMAT since certain sequences of characters have a special meaning to FORMAT. To safely print an arbitrary string—say, the value of a variable s—with FORMAT you should write (format t "~a" s).