Common Lisp the Language, 2nd Edition

Next: Character Construction and Up: Characters Previous: Character Attributes

# 13.2. Predicates on Characters

The predicate `characterp` may be used to determine whether any Lisp object is a character object.

[Function]
`standard-char-p char`

The argument char must be a character object. `standard-char-p` is true if the argument is a ``standard character,'' that is, an object of type `standard-char`.

Note that any character with a non-zero bits or font attribute is non-standard.

[Function]
`graphic-char-p char`

The argument char must be a character object. `graphic-char-p` is true if the argument is a ``graphic'' (printing) character, and false if it is a ``non-graphic'' (formatting or control) character. Graphic characters have a standard textual representation as a single glyph, such as `A` or `*` or `=`. By convention, the space character is considered to be graphic. Of the standard characters all but `#\Newline` are graphic. The semi-standard characters `#\Backspace`, `#\Tab`, `#\Rubout`, `#\Linefeed`, `#\Return`, and `#\Page` are not graphic.

Programs may assume that graphic characters of font 0 are all of the same width when printed, for example, for purposes of columnar formatting. (This does not prohibit the use of a variable-pitch font as font 0, but merely implies that every implementation of Common Lisp must provide some mode of operation in which font 0 is a fixed-pitch font.) Portable programs should assume that, in general, non-graphic characters and characters of other fonts may be of varying widths.

Any character with a non-zero bits attribute is non-graphic.

[Function]
`string-char-p char`

The argument char must be a character object. `string-char-p` is true if char can be stored into a string, and otherwise is false. Any character that satisfies `standard-char-p` also satisfies `string-char-p`; others may also.

X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to eliminate `string-char-p`.

[Function]
`alpha-char-p char`

The argument char must be a character object. `alpha-char-p` is true if the argument is an alphabetic character, and otherwise is false.

If a character is alphabetic, then it is perforce graphic. Therefore any character with a non-zero bits attribute cannot be alphabetic. Whether a character is alphabetic may depend on its font number.

Of the standard characters (as defined by `standard-char-p`), the letters `A` through `Z` and `a` through `z` are alphabetic.

[Function]
`upper-case-p char
``lower-case-p char
``both-case-p char`

The argument char must be a character object.

`upper-case-p` is true if the argument is an uppercase character, and otherwise is false.

`lower-case-p` is true if the argument is a lowercase character, and otherwise is false.

`both-case-p` is true if the argument is an uppercase character and there is a corresponding lowercase character (which can be obtained using `char-downcase`), or if the argument is a lowercase character and there is a corresponding uppercase character (which can be obtained using `char-upcase`).

If a character is either uppercase or lowercase, it is necessarily alphabetic (and therefore is graphic, and therefore has a zero bits attribute). However, it is permissible in theory for an alphabetic character to be neither uppercase nor lowercase (in a non-Roman font, for example).

Of the standard characters (as defined by `standard-char-p`), the letters `A` through `Z` are uppercase and `a` through `z` are lowercase.

[Function]
`digit-char-p char &optional (radix 10)`

The argument char must be a character object, and radix must be a non-negative integer. If char is not a digit of the radix specified by radix, then `digit-char-p` is false; otherwise it returns a non-negative integer that is the ``weight'' of char in that radix.

Digits are necessarily graphic characters.

Of the standard characters (as defined by `standard-char-p`), the characters `0` through `9`, `A` through `Z`, and `a` through `z` are digits. The weights of `0` through `9` are the integers 0 through 9, and of `A` through `Z` (and also `a` through `z`) are 10 through 35. `digit-char-p` returns the weight for one of these digits if and only if its weight is strictly less than radix. Thus, for example, the digits for radix 16 are

    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

Here is an example of the use of `digit-char-p`:

    (defun convert-string-to-integer (str &optional (radix 10))
      "Given a digit string and optional radix, return an integer."
      (do ((j 0 (+ j 1))
           (n 0 (+ (* n radix)
                   (or (digit-char-p (char str j) radix)
                       (error "Bad radix-~D digit: ~C"
                              radix
                              (char str j))))))
          ((= j (length str)) n)))

[Function]
`alphanumericp char`

The argument char must be a character object. `alphanumericp` is true if char is either alphabetic or numeric. By definition,

    (alphanumericp x)
       == (or (alpha-char-p x) (not (null (digit-char-p x))))

Alphanumeric characters are therefore necessarily graphic (as defined by the predicate `graphic-char-p`).

Of the standard characters (as defined by `standard-char-p`), the characters `0` through `9`, `A` through `Z`, and `a` through `z` are alphanumeric.

[Function]
`char= character &rest more-characters
``char/= character &rest more-characters
``char< character &rest more-characters
``char> character &rest more-characters
``char<= character &rest more-characters
``char>= character &rest more-characters`

The arguments must all be character objects. These functions compare the objects using the implementation-dependent total ordering on characters, in a manner analogous to numeric comparisons by `=` and related functions.

The total ordering on characters is guaranteed to have the following properties:

- The standard alphanumeric characters obey the following partial ordering:

      A<B<C<D<E<F<G<H<I<J<K<L<M<N<O<P<Q<R<S<T<U<V<W<X<Y<Z
      to 0pta<b<c<d<e<f<g<h<i<j<k<l<m<n<o<                              p<q<r<s<t<u<v<w<x<y<z
      0<1<2<3<4<5<6<7<8<9
      either 9<A or Z<0
      either 9<a or z<0

  This implies that alphabetic ordering holds within each case (upper and lower), and that the digits as a group are not interleaved with letters. However, the ordering or possible interleaving of uppercase letters and lowercase letters is unspecified. (Note that both the ASCII and the EBCDIC character sets conform to this specification. As it happens, neither ordering interleaves uppercase and lowercase letters: in the ASCII ordering, `9<A` and `Z<a`, whereas in the EBCDIC ordering `z<A` and `Z<0`.)

- If two characters have the same bits and font attributes, then their ordering by `char<` is consistent with the numerical ordering by the predicate `<` on their code attributes.

- If two characters differ in any attribute (code, bits, or font), then they are different.

X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to replace the notion of bits and font attributes with that of implementation-defined attributes.

- If two characters have identical implementation-defined attributes, then their ordering by `char<` is consistent with the numerical ordering by the predicate `<` on their codes, and similarly for `char>`, `char<=`, and `char>=`.

- If two characters differ in any implementation-defined attribute, then they are not `char=`.

The total ordering is not necessarily the same as the total ordering on the integers produced by applying `char-int` to the characters (although it is a reasonable implementation technique to use that ordering).

While alphabetic characters of a given case must be properly ordered, they need not be contiguous; thus `(char<= #\a x #\z)` is not a valid way of determining whether or not `x` is a lowercase letter. That is why a separate `lower-case-p` predicate is provided.

    (char= #\d #\d) is true.
    (char/= #\d #\d) is false.
    (char= #\d #\x) is false.
    (char/= #\d #\x) is true.
    (char= #\d #\D) is false.
    (char/= #\d #\D) is true.
    (char= #\d #\d #\d #\d) is true.
    (char/= #\d #\d #\d #\d) is false.
    (char= #\d #\d #\x #\d) is false.
    (char/= #\d #\d #\x #\d) is false.
    (char= #\d #\y #\x #\c) is false.
    (char/= #\d #\y #\x #\c) is true.
    (char= #\d #\c #\d) is false.
    (char/= #\d #\c #\d) is false.
    (char< #\d #\x) is true.
    (char<= #\d #\x) is true.
    (char< #\d #\d) is false.
    (char<= #\d #\d) is true.
    (char< #\a #\e #\y #\z) is true.
    (char<= #\a #\e #\y #\z) is true.
    (char< #\a #\e #\e #\y) is false.
    (char<= #\a #\e #\e #\y) is true.
    (char> #\e #\d) is true.
    (char>= #\e #\d) is true.
    (char> #\d #\c #\b #\a) is true.
    (char>= #\d #\c #\b #\a) is true.
    (char> #\d #\d #\c #\a) is false.
    (char>= #\d #\d #\c #\a) is true.
    (char> #\e #\d #\b #\c #\a) is false.
    (char>= #\e #\d #\b #\c #\a) is false.
    (char> #\z #\A) may be true or false.
    (char> #\Z #\a) may be true or false.

There is no requirement that `(eq c1 c2)` be true merely because `(char= c1 c2)` is true. While `eq` may distinguish two character objects that `char=` does not, it is distinguishing them not as characters, but in some sense on the basis of a lower-level implementation characteristic. (Of course, if `(eq c1 c2)` is true, then one may expect `(char= c1 c2)` to be true.) However, `eql` and `equal` compare character objects in the same way that `char=` does.

[Function]
`char-equal character &rest more-characters
``char-not-equal character &rest more-characters
``char-lessp character &rest more-characters
``char-greaterp character &rest more-characters
``char-not-greaterp character &rest more-characters
``char-not-lessp character &rest more-characters`

The predicate `char-equal` is like `char=`, and similarly for the others, except according to a different ordering such that differences of bits attributes and case are ignored, and font information is taken into account in an implementation-dependent manner.

X3J13 voted in March 1989 (CHARACTER-PROPOSAL) to replace the notion of bits and font attributes with that of implementation-defined attributes. The effect, if any, of each such attribute on the behavior of `char-equal`, `char-not-equal`, `char-lessp`, `char-greaterp`, `char-not-greaterp`, and `char-not-lessp` must be specified as part of the definition of that attribute.

For the standard characters, the ordering is such that `A=a`, `B=b`, and so on, up to `Z=z`, and furthermore either `9<A` or `Z<0`. For example:

    (char-equal #\A #\a) is true.
    (char= #\A #\a) is false.
    (char-equal #\A #\Control-A) is true.

The ordering may depend on the font information. For example, an implementation might decree that `(char-equal #\p #\p)` be true, but that `(char-equal #\p #\`pi`)` be false (where `#\`pi is a lowercase `p` in some font). Assuming italics to be in font 1 and the Greek alphabet in font 2, this is the same as saying that `(char-equal #0\p #1\p)` may be true and at the same time `(char-equal #0\p #2\p)` may be false.

Next: Character Construction and Up: Characters Previous: Character Attributes