{Begin SubSec CLISP Character Operators} {Title CLISP Character Operators} {Text {index infix operators in CLISP} {index prefix operators in CLISP} CLISP recognizes a number of special characters operators, both prefix and infix, which are translated into common expressions. For example, the character {lisp +} is recognized to represent addition, so CLISP translates the litatom {lisp A+B} to the form {lisp (IPLUS A B)}. Note that CLISP is envoked, and this translation is made, only if an error occurs, such as an unbound atom error or an undefined function error for the perfectly legitamate litatom {lisp A+B}. Therefore the user may choose not to use these facilities with no penalty, similar to other CLISP facilities. The user has a lot of flexability in using CLISP character operators. A list, can always be substituted for a litatom, and vice versa, without changing the interpretation of a phrase. For example, if the value of {lisp (FOO X)} is {lisp A}, and the value of {lisp (FIE Y)} is {lisp B}, then {lisp (LIST (FOO X)+(FIE Y))} has the same value as {lisp (LIST A+B)}. Note that the first expression is a list of {it four} elements: the atom "{lisp LIST}", the list "{lisp (FOO X)}", the atom "+", and the list "{lisp (FIE X)}", whereas the second expression, {lisp (LIST A+B)}, is a list of only {it two} elements: the litatom "{lisp LIST}" and the litatom "{lisp A+B}". Since {lisp (LIST (FOO X)+(FIE Y))} is indistinguishable from {lisp (LIST (FOO X){sp}+{sp}(FIE Y))} because spaces before or after parentheses have no effect on the Interlisp READ program,{foot CLISP does not use its own special READ program because this would require the user to explicitly identify CLISP expressions, instead of being able to intermix Interlisp and CLISP. }{comment endfootnote} to be consistent, extra spaces have no effect on atomic operands either. In other words, CLISP will treat {lisp (LIST A+{sp}B)}, {lisp (LIST A{sp}+B)}, and {lisp (LIST A{sp}+{sp}B)} the same as {lisp (LIST A+B)}. {Def {Type (CLISP Operator)} {Name +}} {Def {Type (CLISP Operator)} {Name -}} {Def {Type (CLISP Operator)} {Name *}} {Def {Type (CLISP Operator)} {Name /}} {Def {Type (CLISP Operator)} {Name ↑} {Text CLISP recognizes {lisp +}, {lisp -}, {lisp *}, {lisp /}, and {lisp ↑} as the normal arithmetic infix operators. {lisp -} is also recognized as the prefix operator, unary minus. These are converted to {fn IPLUS}, {fn IDIFFERENCE} (or in the case of unary minus, {fn IMINUS}), {fn ITIMES}, {fn IQUOTIENT}, and {fn EXPT}. The {lisp I} in {fn IPLUS} denotes integer arithmetic, i.e., {fn IPLUS} converts its arguments to integers, and returns an integer value. Interlisp also contains floating point arithmetic functions as well as mixed arithmetic functions. Floating point arithmetic functions are used in the translation if one or both of the operands are themselves floating point numbers, e.g., {lisp X+1.5} translates as {lisp (FPLUS X 1.5)}. In addition, CLISP contains a facility for declaring which type of arithmetic is to be used, either by making a global declaration, or by separate declarations about individual functions or variables (see {PageRef Tag CLISPdeclarations}). The usual precedence rules{index precedence rules for CLISP operators} apply (although these can be easily changed by the user), i.e., {lisp *} has higher precedence than {lisp +} so that {lisp A+B*C} is the same as {lisp A+(B*C)}, and both {lisp *} and {lisp /} are lower than {lisp ↑} so that {lisp 2*X↑2} is the same as {lisp 2*(X↑2)}. Operators of the same precedence group from left to right, e.g., {lisp A/B/C} is equivalent to {lisp (A/B)/C}. Minus is binary whenever possible, i.e., except when it is the first operator in a list, as in {lisp (-A)} or {lisp (-A)}, or when it immediately follows another operator, as in {lisp A*-B}. Note that grouping with parentheses can always be used to override the normal precedence grouping, or when the user is not sure how a particular expression will parse. The complete order of precedence for CLISP operators is given below. Note that {lisp +} in front of a number will disappear when the number is read, e.g., {lisp (FOO X +2)} is indistinguishable from {lisp (FOO X 2)}. This means that {lisp (FOO X +2)} will not be interpreted as CLISP, or be converted to {lisp (FOO (IPLUS X 2))}. Similarly, {lisp (FOO X -2)} will not be interpreted the same as {lisp (FOO X-2)}. To circumvent this, always type a space between the {lisp +} or {lisp -} and a number if an infix operator is intended, e.g., write {lisp (FOO X + 2)}. }} {Def {Type (CLISP Operator)} {Name =}} {Def {Type (CLISP Operator)} {Name GT}} {Def {Type (CLISP Operator)} {Name LT}} {Def {Type (CLISP Operator)} {Name GE}} {Def {Type (CLISP Operator)} {Name LE} {Text These are infix operators for "Equal", "Greater Than", "Less Than", "Greater Than or Equal", and "Less Than or Equal". {lisp GT}, {lisp LT}, {lisp GE}, and {lisp LE} are all affected by the same declarations as {lisp +} and {lisp *}, with the initial default to use {fn IGREATERP} and {fn ILESSP}. Note that only single character operators, e.g., {lisp +}, {lisp ←}, {lisp =}, etc., can appear in the {emphasize interior} of an atom. All other operators must be set off from identifiers with spaces. For example, {lisp XLTY} will not be recognized as CLISP. In some cases, DWIM will be able to diagnose this situation as a run-on spelling error, in which case after the atom is split apart, CLISP will be able to perform the indicated transformation. }} A number of lisp functions, such as {lisp EQUAL}, {lisp MEMBER}, {lisp AND}, {lisp OR}, etc., can also be treated as CLISP infix operators.{foot Currently the complete list is {lisp MEMBER}, {lisp MEMB}, {lisp FMEMB}, {lisp ILESSP}, {lisp IGREATERP}, {lisp LESSP}, {lisp GREATERP}, {lisp FGTP}, {lisp EQ}, {lisp NEQ}, {lisp EQP}, {lisp EQUAL}, {lisp OR}, and {lisp AND}. New infix operators can be easily added, as described in {PageRef Tag AddingCLISPinfix}. Spelling correction on misspelled infix operators is peformed using {var CLISPINFIXSPLST}{index CLISPINFIXSPLST Var} as a spelling list.{index spelling lists}{index spelling correction} }{comment endfootnote} {lisp AND} is higher than {lisp OR}, and both {lisp AND} and {lisp OR} are lower than the other infix operators, so {lisp (X OR Y AND Z)} is the same as {lisp (X OR (Y AND Z))}, and {lisp (X AND Y EQUAL Z)} is the same as {lisp (X AND (Y EQUAL Z))}. All of the infix predicates have lower precedence than Interlisp forms, since it is far more common to apply a predicate to two forms, than to use a Boolean as an argument to a function. Therefore, {lisp (FOO X GT FIE Y)} is translated as {lisp ((FOO X) GT (FIE Y))}, rather than as {lisp (FOO (X GT (FIE Y)))}. However, the user can easily change this. {Def {Type (CLISP Operator)} {Name :} {Text {lisp {arg X}:{arg N}} extracts the {arg N}th element of the list {arg X}. {lisp FOO:3} specifies the third element of {lisp FOO}, or {lisp (CADDR FOO)}. If {arg N} is less than zero, this indicates elements counting from the end of the list; i.e. {lisp FOO:-1} is the last element of {lisp FOO}. {lisp :} operators can be nested, so {lisp FOO:1:2} means the second element of the first element of {lisp FOO}, or {lisp (CADAR FOO)}. The {lisp :} operator can also be used for extracting substructures of records (see {PageRef Tag RecordPackage}). Record operations are implemented by replacing expressions of the form {lisp X:FOO} by {index FETCH (in record package)}{lisp (fetch FOO of X)}. Both lower and upper case are acceptable. {lisp :} is also used to indicate operations in the pattern match facility ({PageRef Tag PatternMatch}). }} {Def {Type (CLISP Operator)} {Name ::} {Text {lisp {arg X}:{arg N}}, returns the {arg N}th {it tail} of the list {arg X}. For example, {lisp FOO::3} is {lisp (CDDDR FOO)}, and {lisp FOO::-1} is {lisp (LAST FOO)}. }} {Def {Type (CLISP Operator)} {Name ←} {Text {lisp ←} is used to indicate assignment.{index assignments (in CLISP)} For example, {lisp X←Y} translates to {lisp (SETQ X Y)}. If {lisp X} does not have a value, and is not the name of one of the bound variables of the function in which it appears, spelling correction is attempted. However, since this may simply be a case of assigning an initial value to a new free variable, DWIM will always ask for approval before making the correction. In conjunction with {lisp :} and {lisp ::}, {lisp ←} can also be used to perform a more general type of assignment, involving structure modification. For example, {lisp X:2←Y} means "make the second element of {lisp X} {it be} {lisp Y}", in Interlisp terms {lisp (RPLACA (CDR X) Y)}. Note that the {it value} of this operation is the value of {fn RPLACA}, which is {lisp (CDR X)}, rather than {lisp Y}. Negative numbers can also be used, e.g., {lisp X:-2←Y}, which translates to {lisp (RPLACA (NLEFT X 2) Y)}. The user can indicate he wants {fn /RPLACA} and {fn /RPLACD} used (undoable version of {fn RPLACA} and {fn RPLACD}, see {PageRef Tag Undoing}), or {fn FRPLACA} and {fn FRPLACD} (fast versions of {fn RPLACA} and {fn RPLACD}, see {PageRef Fn FRPLACA}), by means of CLISP declarations ({PageRef Tag CLISPdeclarations}).{index declarations (in CLISP)} The initial default is to use {fn RPLACA} and {fn RPLACD}. {lisp ←} is also used to indicate assignment in record operations ({lisp X:FOO←Y} translates to {index REPLACE (in record package)}{lisp (replace FOO of X with Y)}.), and pattern match operations ({PageRef Tag PatternMatch}). {lisp ←} has different precedence on the left from on the right. On the left, {lisp ←} is a "tight" operator, i.e., high precedence, so that {lisp A+B←C} is the same as {lisp A+(B←C)}. On the right, {lisp ←} has broader scope so that {lisp A←B+C} is the same as {lisp A←(B+C)}. On typein, {lisp $←{arg FORM}} ({lisp <esc>←{arg FORM}}){index $ (<esc>) (in CLISP)} is equivalent to set the "last thing mentioned".{foot i.e., is equivalent to {lisp (SET LASTWORD {arg FORM})}.{note check this} See {PageRef Var LASTWORD}.{index LASTWORD Var} }{comment endfootnote} For example, immediately after examining the value of {lisp LONGVARIABLENAME}, the user could set it by typing {lisp $←} followed by a form. }} Note that an atom of the form {lisp X←Y}, appearing at the top level of a {lisp PROG}, will {it not} be recognized as an assignment statement because it will be interpreted as a {fn PROG} label by the Interlisp interpreter, and therefore will not cause an error, so DWIM and CLISP will never get to see it. Instead, one must write {lisp (X←Y)}. {Def {Type (CLISP Operator)} {Name <}} {Def {Type (CLISP Operator)} {Name >} {Text Angle brackets are used in CLISP to indicate list construction.{index constructing lists (in CLISP)}{index <,> (use in CLISP)} The appearance of a "{lisp <}" corresponds to a "{lisp (}" and indicates that a list is to be constructed containing all the elements up to the corresponding "{lisp >}". For example, {lisp <A B <C>>} translates to {lisp (LIST A B (LIST C))}. {lisp !}{index ! (use with <,> in CLISP)} can be used to indicate that the next expression is to be inserted in the list as a {it segment}, e.g., {lisp <A B ! C>} translates to {lisp (CONS A (CONS B C))} and {lisp <! A ! B C>} to {lisp (APPEND A B (LIST C))}. {lisp !!}{index !! (use with <,> in CLISP)} is used to indicate that the next expression is to be inserted as a segment, and furthermore, all list structure to its right in the angle brackets is to be physically attached to it, e.g., {lisp <!! A B>} translates to {lisp (NCONC1 A B)}, and {lisp <!!A !B !C>} to {lisp (NCONC A (APPEND B C))}. Not {lisp (NCONC (APPEND A B) C)}, which would have the same value, but would attach {lisp C} to {lisp B}, and not attach either to {lisp A}. Note that {lisp <}, {lisp !}, {lisp !!}, and {lisp >} need not be separate atoms, for example, {lisp <A B ! C>} may be written equally well as {lisp < A B !C >}. Also, arbitrary Interlisp or CLISP forms may be used within angle brackets. For example, one can write {lisp <FOO←(FIE X) ! Y>} which translates to {lisp (CONS (SETQ FOO (FIE X)) Y)}. {fn CLISPIFY} converts expressions in {fn CONS}, {fn LIST}, {fn APPEND}, {fn NCONC}, {fn NCONC1}, {fn /NCONC}, and {fn /NCONC1} into equivalent CLISP expressions using {lisp <}, {lisp >}, {lisp !}, and {lisp !!}. Note: brackets differ from other CLISP operators. For example, {lisp <A B 'C>} translates to {lisp (LIST A B (QUOTE C))} even though following {lisp '}, all {it operators} are ignored for the rest of the identifier. (This is true only if a previous unmatched {lisp <} has been seen, e.g., {lisp (PRINT 'A>B)} will print the atom {lisp A>B}.) Note however that {lisp <A B '{sp}C> D>} is equivalent to {lisp (LIST A B (QUOTE C>) D)}. }} {Def {Type (CLISP Operator)} {Name '} {Text CLISP recognizes {lisp '} as a prefix operator. {lisp '} means {lisp QUOTE} when it is the first character in an identifier, and is ignored when it is used in the interior of an identifier. Thus, {lisp X='Y} means {lisp (EQ X (QUOTE Y))}, but {lisp X=CAN'T} means {lisp (EQ X CAN'T)}, {it not} {lisp (EQ X CAN)} followed by {lisp (QUOTE T)}. This enables users to have variable and function names with {lisp '} in them (so long as the {lisp '} is not the first character). Following {lisp '}, all operators are ignored for the rest of the identifier, e.g., {lisp '*A} means {lisp (QUOTE *A)}, and {lisp 'X=Y} means {lisp (QUOTE X=Y)}, not {lisp (EQ (QUOTE X) Y)}. To write {lisp (EQ (QUOTE X) Y)}, one writes {lisp Y='X}, or {lisp 'X =Y}. This is one place where an extra space does make a difference. On typein, {lisp '$} (i.e., {lisp '<esc>}) is equivalent to {lisp (QUOTE {arg VALUE-OF-LASTWORD})}{index $ (<esc>) (in CLISP)} (see {PageRef Var LASTWORD}). For example, after calling {fn PRETTYPRINT} on {lisp LONGFUNCTION}, the user could move its definition to {lisp FOO} by typing {lisp (MOVD '$ 'FOO)}.{foot {it Not} {lisp (MOVD $ 'FOO)}, which would be equivalent to {lisp (MOVD LONGFUNCTION 'FOO)}, and would (probably) cause a {lisp U.B.A. LONGFUNCTION} error, nor {lisp MOVD($ FOO)}, which would actually move the definition of {lisp $} to {lisp FOO}, since DWIM and the spelling corrector would never be invoked. }{comment endfootnote} }} {Def {Type (CLISP Operator)} {Name ~} {Text CLISP recognizes {lisp ~} as a prefix operator meaning {lisp NOT}. {lisp ~} can negate a form, as in {lisp ~(ASSOC X Y)}, or ~{lisp X}, or negate an infix operator, e.g., {lisp (A ~GT B)} is the same as {lisp (A LEQ B)}. Note that {lisp ~A=B} means {lisp (EQ (NOT A) B)}. When {lisp ~} negates an operator, e.g., {lisp ~=}, {lisp ~LT}, the two operators are treated as a single operator whose precedence is that of the second operator. When {lisp ~} negates a function, e.g., {lisp (~FOO X Y)}, it negates the whole form, i.e., {lisp (~(FOO X Y))}. }} {index order of precedence of CLISP operators} {Begin Table ORDER OF PRECEDENCE OF CLISP OPERATORS} {VSKIP 0} {COLUMN} {Underline} {Next Order of Prededence of CLISP Operators:} {Next {lisp '}} {Next {lisp :}} {Next {lisp ←} (left precedence)} {Next {lisp -} (unary), {lisp ~}} {Next {lisp ↑}} {Next {lisp *}, {lisp /}} {Next {lisp +}, {lisp -} (binary)} {Next {lisp ←} (right precedence)} {Next {lisp =}} {Next Interlisp forms} {Next {lisp LT}, {lisp GT}, {lisp EQUAL}, {lisp MEMBER}, etc.} {Next {lisp AND}} {Next {lisp OR}} {Next {lisp IF}, {lisp THEN}, {lisp ELSEIF}, {lisp ELSE}} {Next iterative statement operators} {End Table ORDER OF PRECEDENCE OF CLISP OPERATORS} }{End SubSec CLISP Character Operators}