{Begin SubSec CLISP Character Operators}
{Title CLISP Character Operators}
{Text

{index *PRIMARY* Infix operators in CLISP}
{index *PRIMARY* 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, 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)}.  


Note:  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.



{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 PLUS}, {fn DIFFERENCE} (or in the case of unary minus, {fn MINUS}), {fn TIMES}, {fn QUOTIENT}, and {fn EXPT}.

Normally, CLISP uses the "generic" arithmetic functions {lisp PLUS}, {lisp TIMES}, etc.  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 *PRIMARY* 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 GREATERP} and {fn LESSP}.


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.  New infix operators can be easily added (see {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}

{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 {lisp (fetch FOO of X)}.{index FETCH (Record operator)}  Both lower and upper case are acceptable.


{lisp :} is also used to indicate operations in the pattern match facility ({PageRef Tag PatternMatch}).  {lisp X:(& 'A -- 'B)} translates to {lisp (match X with (& 'A -- 'B))}
}}


{Def {Type (CLISP Operator)}   {Name .}
{Text
In combination with {lisp :}, a period can be used to specify the "data path" for record operations.  For example, if {lisp FOO} is a field of the {lisp BAR} record, {lisp X:BAR.FOO} is translated into {lisp (fetch (BAR FOO) of X)}.  Subrecord fields can be specified with multiple periods:  {lisp X:BAR.FOO.BAZ} translates into {lisp (fetch (BAR FOO BAZ) of X)}.

Note:  If a record contains fields with periods in them, {fn CLISPIFY} will not translate a record operation into a form using periods to specify the data path.  For example, {fn CLISPIFY} will NOT translate {lisp (fetch A.B of X)} into {lisp X:A.B}.
}}



{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}).  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 (Record operator)}{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}} (where {lisp $} is the escape key){index Escape ($) (in CLISP)}{index $ (escape) (in CLISP)} is equivalent to set the "last thing mentioned", i.e., is equivalent to {lisp (SET LASTWORD {arg FORM})}{note check this} (see {PageRef Var LASTWORD}).{index LASTWORD Var}  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, {index Escape ($) (in CLISP)}{index $ (escape) (in CLISP)}{lisp '$} (escape) is equivalent to {lisp (QUOTE {arg VALUE-OF-LASTWORD})} (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)}.

Note that this is 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.
}}


{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))}.
}}


Order of Prededence of CLISP Operators:

{index Order of precedence of CLISP operators}

{Begin Lispcode}

'
:
← {rm (left precedence)}
- {rm (unary),} ~
↑
*, /
+, - {rm (binary)}
← {rm (right precedence)}
=
{rm Interlisp forms}
LT, GT, EQUAL, MEMBER, {rm etc.}
AND
OR
IF, THEN, ELSEIF, ELSE
{rm iterative statement operators}
{End Lispcode}


}{End SubSec CLISP Character Operators}