Strings are a type of array which are constants (they self-evaluate) and have as their printed representation a sequence of characters enclosed in quote marks, for example "foo bar" . Strings are the right data type to use for text-processing. The functions described in this section provide a variety of useful operations on strings. Several of the functions actually work on any type of 1-dimensional array and may be useful for other than string processing. art-16b arrays (arrays of 16-bit positive numbers) are often used as strings; the extra bits allow for an expanded character set. In place of a string, most of these functions will accept a symbol or a fixnum as an argument, and will coerce it into a string. Given a symbol, its print name, which is a string, will be used. Given a fixnum, a 1 character long string containing the character designated by that fixnum will be used. Note that the length of a string is computed using array-active-length , so that if a string has an array-leader, element 0 of the leader (called the fill pointer ) will be taken as the length. Since strings are arrays, the usual array-referencing function aref is used to extract the characters of the string as fixnums. For example,
(aref "frob" 1) => 162 ;lower-case rIt is also legal to store into strings (using aset ). As with rplaca on lists, this changes the actual object; one must be careful to understand where side-effects will propagate to.
Examples: (string-equal "Foo" "foo") => t (string-equal "foo" "bar") => nil (string-equal "element" "select" 0 1 3 4) => t
Examples: To compare the two strings foo and bar: (%string-equal foo 0 bar nil) To see if the string foo starts with the characters "bar": (%string-equal foo 0 "bar" 0 3)
Example: (substring "Nebuchadnezzar" 4 8) => "chad"
Example: (string-append 41 "foo" 41) => "!foo!"
Example: (string-trim '(40) " Dr. No ") => "Dr. No"
Example: (string-search-char 101 "banana") => 1
Example: (string-search-char 102 "banana") => 1
Example: (string-search "an" "banana") => 1 (string-search "an" "banana" 2) => 3
Example: (string-search-set '(116 117) "banana") => 2
Example: (string-search-not-set '(141 142) "banana") => 2
Example: (string-reverse-search-char 156 "banana") => 4
Example: (string-reverse-search-not-char 101 "banana") => 4
Example: (string-reverse-search "na" "banana") => 4
(string-reverse-search-set '(141 142) "banana") => 5
(string-reverse-search-not-set '(141 156) "banana") => 0
(with-input-from-string (var string ) body )evaluates the forms in body with the variable var bound to a stream which reads characters from the string which is the value of the form string . The value of the special form is the value of the last form in its body. The stream is a "downward closure", so be careful what you do with it. You cannot use it after control leaves the body, and you cannot nest two with-input-from-string special forms and use both streams since the special-variable bindings associated with the stream will conflict. It is done this way to avoid any consing. After string you may optionally specify two additional "arguments".
(with-input-from-string (var string index ) body )uses index as the starting index into the string, and updates it when it is done to the index of the first character not read (the length of the string if all of it was read.) Since index is updated it may not be a general expression; it must be a variable or a setf -able reference. The index is not updated in the event of an abnormal exit from the body, such as a *throw . Use of the index feature prevents multiple values from being returned out of the body, currently.
(with-input-from-string (var string index limit ) body )uses the value of the form limit in place of the length of the string if it is not nil . If you want to specify a limit but not an index , put nil for index .
(with-output-to-string (var ) body )evaluates the forms in body with var bound to a stream which saves the characters output to it in a string. The value of the special form is the string.
(with-output-to-string (var string ) body )will append its output to the string which is the value of the form string . (This is like the string-nconc function.) The value returned is the value of the last form in the body, rather than the string. Multiple values are not returned. If string has an array-leader, element 0 of the array-leader will be used as the fill-pointer. If string is too small to contain all the output, adjust-array-size will be used to make it bigger.
(with-output-to-string (var string index ) body )is similar to the above except that index is a variable or setf -able reference which contains the index of the next character to be stored into. It must be initialized outside the with-output-to-string and will be updated upon normal exit. The stream is a "downward closure", so be careful what you do with it. You cannot use it after control leaves the body, and you cannot nest two with-input-from-string special forms and use both streams since the special-variable bindings associated with the stream will conflict. It is done this way to avoid any consing.
Examples: (ascii 101) => A (ascii 56) => /.The symbol returned is interned in the user package.
Example: (maknam '(a b 60 d)) => ab0d
"~S" ; This is an S directive with no parameters. "~3,4:@s" ; This is an S directive with two parameters, 3 and 4, ; and both the colon and atsign flags.Sometimes a numeric parameter is used to specify a character, for instance the padding character in a right- or left-justifying operation. In this case a single quote ("' ") followed by the desired character may be used as a numeric argument. For example, you can use
"~5,'0d"to print a decimal number in five columns with leading zeros. The kinds of directives will now be described. arg will be used to refer to the next argument from args .
~D | arg , a number, is printed as a decimal integer. ~nD uses a column width of n ; spaces are inserted on the left if the number requires less than n columns for its digits and sign. If the number doesn't fit in n columns, additional columns are used as needed. ~n,mD uses m as the pad character instead of 40 (space). If arg is not a number, it is printed in ~A format. The @ modifier causes the number's sign to be printed always; the default is only to print it if the number is negative. The : modifier causes commas to be printed betweens of three digits; the third numeric parameter may be used to change the character used as the comma. Thus the most general form of ~D is ~mincol,padchar,commacharD . | |
~O | This is just like ~D but prints in octal instead of decimal. | |
~F | arg is printed in floating point. ~nF rounds arg to a precision of n digits. The minimum value of n is 2, since a decimal point is always printed. If the magnitude of arg is too large or too small, it is printed in exponential notation. If arg is not a number, it is printed in ~A format. | |
~E | arg is printed in exponential notation. This is identical to ~F , including the use of a numeric parameter to specify the number of digits, except that the number is always printed with a trailing exponent, even if it is within a reasonable range. | |
~A | arg , any Lisp object, is printed without slashification (like princ ). ~:A prints () if arg is nil ; this is useful when printing something that is always supposed to be a list. ~nA inserts spaces on the right, if necessary, to make the column width at least n . The @ modifier causes the spaces to be inserted on the left rather than the right. ~mincol,colinc,minpad,padcharA is the full form of ~A , which allows elaborate control of the padding. The string is padded on the right with at least minpad copies of padchar ; padding characters are then inserted colinc characters at a time until the total width is at least mincol . The defaults are 0 for mincol and minpad , 1 for colinc , and space for padchar . | |
~S | This is just like ~A , but arg is printed with slashification (like prin1 rather than princ ). | |
~C | (character arg) is printed as a keyboard character (see LINK:(%%kbd)).
Any control bits are printed first by representing them with Greek letters:
alpha (Control), beta (Meta), epsilon (Control and Meta),
lambda (Hyper), pi (Super).
If the character itself is alpha, beta, epsilon, lambda, pi, or equivalence-sign,
then it is preceded by an equivalence-sign to quote it.
With the colon flag (~:C ), the name of the control bits are spelled out
(e.g. "Control-Meta-F "), and also non-printing characters (those in the 200 to 377 range)
are represented by their names (e.g. "Return ").
With both colon and atsign (~:@C ), the colon-only format is printed, and then
if the character requires the Top, Front, or Greek key(s) to type it,
this fact is mentioned (e.g. "≥ (Top-L) ").
For all three of these formats,
if the character is not a keyboard character but a mouse "character",
it is printed as "Mouse-", the name of the button, "-", and the number of clicks.
With just an atsign (~@C ), the character is printed in such a way that
the READ function can understand it, using "#/ " or "#\ ".
Examples:
(setq a `(44 1440 403 215 611 ,(dpb 1 %%kbd-mouse 11))) (format nil "~{<~C>~}" a) => "<$>< ><>< >< ><Mouse-Middle-Twice>" (format nil "~{<~:C>~}" a) => "<$><Control-Meta-Space><Control-><Return><Control-Tab><Mouse-Middle-Twice>" (format nil "~{<~:@C>~}" a) => "<$><Control-Meta-Space><Control- (Top-X)><Return><Control-Tab><Mouse-Middle-Twice>" (format nil "~{<~@C>~}" a) => "<#//$><#\SPACE><#//><#\RETURN><#\TAB><#\MOUSE-M-2>" | |
~% | Outputs a newline. ~n% outputs n newlines. No argument is used. | |
~& | The :fresh-line operation is performed on the output stream. Unless the stream knows that it is already at the front of a line, this outputs a newline. ~n& does a :fresh-line operation and then outputs n-1 newlines. | |
~| | Outputs a formfeed. ~n| outputs n formfeeds. With a : , performs a :clear-screen operation on the output stream if the stream supports that operation; otherwise it behaves as if no : were present (outputs formfeed(s)). | |
~X | Outputs a space. ~nX outputs n spaces. | |
~~ | Outputs a tilde. ~n~ outputs n tildes. | |
~ <CR> | Tilde immediately followed by a carriage return ignores the carriage return and any whitespace at the beginning of the next line. With a : , the whitespace is left in place. With an @ , the carriage return is left in place. | |
~* | arg is ignored. ~n* ignores the next n arguments. ~:* "ignores backwards"; that is, it backs up in the list of arguments so that the argument last processed will be processed again. ~:n* backs up n arguments. When within a ~{ construct, the ignoring (in either direction) is relative to the list of arguments being processed by the iteration. | |
~P | If arg is not 1 , a lower-case s is printed. ("P" for "plural".) ~:P does the same thing, after doing a ~:* ; that is, it prints a lower-case s if the last argument was not 1. ~@P prints "y" if the argument is 1, or "ies" if it is not. ~:@P does the same thing, but backs up first. | |
~T | Spaces over to a given column. ~n,mT will output sufficient spaces to move the cursor to column n . If the cursor is already past column n , it will output spaces to move it to column n +mk , for the smallest integer value k possible. n and m default to 1 . Without the colon flag, n and m are in units of characters; with it, they are in units of pixels. Note : this operation only works properly on streams that support the :read-cursorpos and :set-cursorpos stream operations (see LINK:(read-cursorpos)). On other streams (and when format is creating a string), any ~T operation will simply output two spaces. | |
~R | If there is no parameter, then arg is printed as a cardinal English number, e.g. four. With the colon modifier, arg is printed as an ordinal number, e.g. fourth. With the atsign modifier, arg is printed as a Roman numeral, e.g. IV. With both atsign and colon, arg is printed as an old Roman numeral, e.g. IIII. If there is a parameter, then it is the radix in which to print the number. The flags and any remaining parameters are used as for the ~D directive. Indeed, ~D is the same as ~10R . The full form here is therefore ~radix,mincol,padchar,commacharR . | |
~n G | "Goes to" the n th argument. ~0G goes back to the first argument in args . Directives after a ~nG will take sequential arguments after the one gone to. When within a ~{ construct, the "goto" is relative to the list of arguments being processed by the iteration. This is an "absolute goto"; for a "relative goto", see ~* . | |
~[str0 ~;str1 ~;... ~;strn ~] | ||
This is a set of alternative control strings. The alternatives
(called clauses )
are separated by ~; and the construct is terminated by ~] .
For example, "~[Siamese ~;Manx ~;Persian ~;Tortoise-Shell ~;Tiger
~;Yu-Hsiang ~]kitty ". The arg th
alternative is selected; 0 selects the first.
If a numeric parameter is given (i.e. ~n[ ),
then the parameter is used instead of an argument
(this is useful only if the parameter is "# ").
If arg is out of range no alternative is selected.
After the selected alternative has been processed, the control string
continues after the ~] .
~[str0 ~;str1 ~;... ~;strn ~:;default ~] has a default case.
If the last ~; used to separate clauses
is instead ~:; , then the last clause is an "else" clause,
which is performed if no other clause is selected.
For example, "~[Siamese ~;Manx ~;Persian ~;Tortoise-Shell ~;Tiger
~;Yu-Hsiang ~:;Unknown ~] kitty ".
~[~tag00 ,tag01 ,... ;str0 ~tag10 ,... ;str1... ~]
allows the clauses to have explicit tags. The parameters to each ~;
are numeric tags for the clause which follows it. That clause is processed
which has a tag matching the argument. If ~:a1,a2,b1,b2,...;
is used, then the following clause is tagged not by single values but
by ranges of values a1 through a2 (inclusive), b1 through b2 , etc.
~:; with no parameters may be used at the end to denote a default clause.
For example, "~[~'+,'-,'*,'//;operator ~'A,'Z,'a,'z;letter ~'0,'9;digit ~:;other ~] ".
~:[false~;true~] selects the false control string
if arg is nil , and selects the true control string otherwise.
~@[true~] tests the argument. If it is not nil ,
then the argument is not used up, but is the next one to be processed,
and the one clause is processed.
If it is nil , then the argument is used up, and the clause is not processed.
(setq prinlevel nil prinlength 5) (format nil "~@[ PRINLEVEL=~D~]~@[ PRINLENGTH=~D]" prinlevel prinlength) => " PRINLENGTH=5" | ||
~; | Separates clauses in ~[ and ~< constructions. It is undefined elsewhere. | |
~] | Terminates a ~[ . It is undefined elsewhere. |
(apply (function format) (list* stream string args)) (format stream "~1{~:}" string args)This will use string as a formatting string. The ~1{ says it will be processed at most once, and the ~:} says it will be processed at least once. Therefore it is processed exactly once, using args as the arguments. As another example, the format function itself uses format-error (a routine internal to the format package) to signal error messages, which in turn uses ferror , which uses format recursively. Now format-error takes a string and arguments, just like format , but also prints some addtitional information: if the control string in ctl-string actually is a string (it might be a list -- see below), then it prints the string and a little arrow showing where in the processing of the control string the error occurred. The variable ctl-index points one character after the place of the error.
(DEFUN FORMAT-ERROR (STRING &REST ARGS) (COND ((STRINGP CTL-STRING) (FERROR NIL "~1{~:}~%~VTSAIL~%~3X/"~A/"~%" STRING ARGS (+ CTL-INDEX 3) CTL-STRING)) (T (FERROR NIL "~1{~:}" STRING ARGS))))This first processes the given string and arguments using ~1{~:} , then tabs a variable amount for printing the down-arrow, then prints the control string between double-quotes. The effect is something like this:
(format t "The item is a ~[Foo~;Bar~;Loser~]." 'quux) >>ERROR: The argument to the FORMAT "~[" command must be a number SAIL "The item is a ~[Foo~;Bar~;Loser~]." SAIL...
(format nil "~10<foo~;bar~>") => "foo bar" (format nil "~10:<foo~;bar~>") => " foo bar" (format nil "~10:@<foo~;bar~>") => " foo bar " (format nil "~10<foobar~>") => " foobar" (format nil "$~10,,'*<~3f~>" 2.59023) => "$******2.59"If ~^ is used within a ~< construct, then only the clauses which were completely processed are used. For example:
(format nil "~15<~S~;~^~S~;~^~S~>" 'foo) => " FOO" (format nil "~15<~S~;~^~S~;~^~S~>" 'foo 'bar) => "BAR FOO" (format nil "~15<~S~;~^~S~;~^~S~>" 'foo 'bar 'baz) => "FOO BAR BAZ"If the first clause of a ~< is terminated with ~:; instead of ~;, then it is used in a special way. All of the clauses are processed (subject to ~^, of course), but the first one is omitted in performing the spacing and padding. When the padded result has been determined, then if it will fit on the current line of output, it is output, and the text for the first clause is discarded. If, however, the padded text will not fit on the current line, then a newline is output, then the text for the first clause, then the padded text. The first clause is always processed, and so any arguments it refers to will be used; the decision is whether to use the resulting piece of text, not whether to process the first clause. If the ~:; has a numeric parameter n, then the padded text must fit on the current line with n character positions to spare to avoid outputting the newline. For example, the control string "~%;; ~{~<;; ~:1; ~S~>~^,~}.~%" can be used to print a list of items separated by commas, without breaking items over line boundaries, and beginning each line with ";; ". The argument 1 in ~:1; accounts for the width of the comma which will follow the justified item if it is not the last element in the list. If ~:; has a second numeric parameter m, then m is used as the width of the line, thus overriding the natural line width of the output stream. To make the preceding example use a line width of 50, one would write "~%;; ~{~<;; ~:1,30; ~S~>~^,~}.~%".
(setq foo "Items:~#[ none~; ~S~; ~S and ~S~:;~@{~#[~1; and~] ~S~^,~}~].") (format nil foo) => "Items: none." (format nil foo 'foo) => "Items: FOO." (format nil foo 'foo 'bar) => "Items: FOO and BAR." (format nil foo 'foo 'bar 'baz) => "Items: FOO, BAR, and BAZ." (format nil foo 'foo 'bar 'baz 'quux) => "Items: FOO, BAR, BAZ, and QUUX."The user can define his own directives. How to do this is not documented here; read the code. Names of user-defined directives longer than one character may be used if they are enclosed in backslashes (e.g. ~4,3\GRAPH\).
Examples: (format nil "foo") => "foo" (setq x 5) (format nil "The answer is ~D." x) => "The answer is 5." (format nil "The answer is ~3D." x) => "The answer is 5." (setq y "elephant") (format nil "Look at the ~A!" y) => "Look at the elephant!" (format nil "The character ~:@C is strange." 1003) => "The character Meta-SAIL (Top-X) is strange." (setq n 3) (format nil "~D item~P found." n n) => "3 items found." (format nil "~R dog~:[s are~; is~] here." n (= n 1)) => "three dogs are here." (format nil "~R dog~[~1; is~:;s are~] here." n) => "three dogs are here." (format nil "Here ~[~1;is~:;are~] ~:*~R pupp~:P." n) => "Here are three puppies."format also allows control-string to be a list of strings and lists, which is processed from left to right. Strings are interpreted as in the simple case. Lists are taken as extended directives; the first element is the directive letter, and the remaining elements are the numeric parameters to the directive. If the car of a list is not a recognized directive, the list is simply evaluated as a form; anything it writes to the standard-output stream will appear in the result of format.