SECTION 2 USING INTERLISP 2.1 Using the INTERLISP Manual - Format, Notation, and Conventions The INTERLISP manual is divided into separate, more or less independent sections. Each section is paginated independently, to facilitate issuing updates of sections. Each section contains an index to key words, functions, and variables contained in that section. In addition, there is a composite index for the entire manual, plus several appendices and a table of contents. INTERLISP is currently implemented on (or implementations are in progress for) at least four different computers. This manual purports to be a reference manual for all implementations of INTERLISP, both present and future. However, since the largest user cummunity is still that of INTERLISP-10, the original implementation for the DEC PDP-10, the manual does contain some implementation dependent material. Where this is the case, the text refers to INTERLISP-10, and is indicated as such. Throughout the manual, terminology and conventions will be offset from the text and typed in italics, frequently at the beginning of a section. For example, one such notational convention is: The names of functions and variables are written in lower case and underlined when they appear in the text. Meta-LISP notation is used for describing forms. Examples: member[x;y] is equivalent to (MEMBER X Y), member[car[x];FOO] is equivalent to (MEMBER (CAR X) (QUOTE FOO)). Note that in meta-LISP notation lower case variables are evaluated, upper case quoted. . notation is used to distinguish between cons and list. e.g., if x=(A B C), (FOO x) is (FOO (A B C)), whereas (FOO . x) is (FOO A B C). In other words, x is cadr of (FOO x) but cdr of (FOO . x). Similarly, y is caddr of (FOO x y), but cddr of (FOO x . y). Note that this convention is in fact followed by the read program, i.e., (FOO . (A B C)) and (FOO A B C) read in as equal structures. Other important conventions are: 2.1 TRUE in INTERLISP means not NIL. The purpose of this is to allow a single function to be used both for the computation of some quantity, and as a test for a condition. For example, the value of member[x;y] is either NIL, or the tail of y beginning with x. Similarly, the value of or is the value of its first TRUE, i.e., non-NIL, expression, and the value of and is either NIL, or the value of its last expression. Although most lists terminate in NIL, the occasional list that ends in an atom, e.g., (A B . C) or worse, a number or string, could cause bizarre effects. Accordingly, we have made the following implementation decision: All functions that iterate through a list, e.g., member, length, mapc, etc. terminate by an nlistp check, rather than the conventional null-check, as a safety precaution against encountering data types which might cause infinite cdr loops, e.g., strings, numbers, arrays. Thus, member[x;(A B . C)] = member[x;(A B)] reverse[(A B . C)] = reverse[(A B)] append[(A B . C);y] = append[(A B);y] 1 For users with an application requiring extreme efficiency, we have provided fast versions of memb, last, nth, assoc, and length which compile open and terminate on NIL checks, and therefore may cause infinite cdr loops if given poorly formed arguments. However, to help detect these situations, fmemb, flast, fnth, fassoc, and flength all generate errors when interpreted if their argument ends in a non-list other than NIL, e.g., BAD ARGUMENT - FLAST. Most functions that set system parameters, e.g., printlevel,linelength, radix, etc., return as their value the old setting. If given NIL as an argument, they return the current value without changing it. All SUBRS, i.e., hand coded functions, such as read, print, eval, cons, etc., have "argument names" selected from U, V, W, X, Y, Z, as described under arglist, Section 8. However, for tutorial purposes, more suggestive names are used in the descriptions of these functions in the text. Most functions whose names end in p are predicates, e.g., numberp, tailp, exprp; most functions whose names end in q are nlambda's, i.e., do not require quoting their arguments, e.g., setq, defineq, nlsetq. ------------------------------------------------------------------------ 1 A NIL check can be executed in only one instruction, an nlistp on INTERLISP-10 requires about 12, although both generate only one word of code. 2.2 "x is equal to y" means equal[x;y] is true, as opposed to "x is eq to y" meaning eq[x;y] is true, i.e., x and y are the same identical LISP pointer. When new literal atoms are created (by the read program, pack, or mkatom), they are provided with a function definition cell initialized to NIL (Section 8), a value cell initialized to the atom NOBIND (Section 16), and a property list initialized to NIL (Section 7). The function definition cell is accessed by the functions getd and putd described in Section 8, the value cell by the functions gettopval and settopval (Section 5), and the property list by the functions getproplist and setproplist, (Section 7). car of NIL and cdr of NIL are always NIL, and the system will resist attempts to change them. The term list refers to any structure created by one or more conses, i.e., it does not have to end in NIL. For example, (A . B) is a list. The function listp, Section 5, is used to test for lists. Note that not being a list does not necessarily imply an atom, e.g., strings and arrays are not lists, nor are they atoms. See Section 10. Many system functions have extra optional arguments for internal use that are not described in the writeups. For example, readline is described as a function of one argument, but arglist[READLINE] returns (RDTBL LINE LISPXFLG). In such cases, the user should just ignore the extra arguments. INTERLISP departs from LISP 1.5 and other LISP dialects in that car of a form is never evaluated. In other words, if car of a form is not an atom with a function definition, and not a function object, i.e., a list car of which is LAMBDA, NLAMBDA, or FUNARG, an error is generated. apply or apply* (Section 8) must be used if the name of a function is to be computed as for example, when functional arguments are applied. 2.2 Using the INTERLISP-10 System on TENEX - An Overview Call INTERLISP-10 by typing LISP followed by a carriage return. INTERLISP will type an identifying message, the date, and a greeting, followed by a "_". This prompt character indicates that the user is "talking to" the top level INTERLISP executive, called evalqt, (for historical reasons), just as "@" indicates the user is talking to Tenex. evalqt calls lispx which accepts inputs in either eval or apply format: if just one expression is typed on a line, it is evaluated; if two expressions are typed, the first is apply-ed to the second. eval and apply are described in Section 8. In both cases, the value is typed, followed by _ indicating INTERLISP is ready for another input. INTERLISP is normally exited via the function logout, i.e., the user types LOGOUT(). However, typing control-C at any point in the computation returns control immediately to Tenex. The user can then continue his program with no ill effects with the Tenex CONTINUE command, even if he interrupted it during a garbage collection. Or he can reenter his program at evalqt with the Tenex REENTER command. The latter is DEFINITELY not advisable if the Control-C was typed during a garbage collection. Typing control-D at any point during a computation 2.3 will return control to evalqt. If typed during a garbage collection, the garbage collection will first be completed, and then control will be returned to INTERLISP's top level, otherwise, control returns immediately. When typing to the INTERLISP read program, typing a control-Q will cause INTERLISP to print "##" and clear the input buffer, i.e., erase the entire line up to the last carriage return. Typing control-A erases the last character typed in, echoing a \ and the erased character. Control- A will not back up beyond the last carriage return. Typing control-W within a call to read or readline will erase the last expression typed, echoing a \\. Control-W will back up to previous lines. Control-O can be used to immediately clear the output buffer, and rubout to 2 immediately clear the input buffer. In addition, typing control-U (in most cases) will cause the INTERLISP editor (Section 9) to be called on the expression being read, when the read is completed. Appendix 3 contains a list of all control characters, and a reference to that part of the manual where they are described. Section 16 describes how the system's interrupt characters can be disabled or redefined, as well as how the user can define his own interrupt characters. Since the INTERLISP read program is normally line-buffered to make 3 possible the action of control-Q, the user must type a carriage return before any characters are delivered to the function requesting input, e.g., 4 _E TC T However, the read program automatically supplies (and prints) this carriage return when a matching right parenthesis is typed, making it unnecessary for the user to do so, e.g., _CONS(A B) (A . B) The INTERLISP read program treats square brackets as "super- parentheses": a right square bracket automatically supplies enough right parentheses to match back to the last left square bracket (in the ------------------------------------------------------------------------ 2 The action of control-Q takes place when it is read. If the user has "typed ahead" several inputs, control-Q will only affect at most the last line of input. Rubout however will clear the entire input buffer as soon as it is typed, i.e., even during a garbage collection. 3 Except following control[T], see Section 14. 4 'C' is used throughout the manual to denote carriage-return. 2.4 expression being read), or if none has appeared, to match the first left parentheses, e.g., (A (B (C]=(A (B (C))), (A [B (C (D] E)=(A (B (C (D))) E). % is the universal escape character for read. Thus to input an atom containing a syntactic delimiter, precede it by %, e.g., AB% (C or %%. See Section 14 for more details. ^V (control-V) can be used to type a control character that would otherwise interrupt the input process, e.g., control-D, control-C, etc. If the character following ^V is A, B, ... or Z, the corresponding control character is input, e.g., ^VA^VB^VC is the atom control-Acontrol-Bcontrol-C. ^V followed by any other character has no effect, i.e., FOO^V1 and FOO1 are identical. For more details, see Appendix 3. Typing ' immediately in front of any expression has the effect of quoting the expression, i.e., (A 'B C) is read as (A (QUOTE B) C). See Section 14. At any point during input, the user can type ?= followed by carriage- return and be given the argument names and corresponding values (if any) of the expression (form) being typed. Typing just ? carriage-return will cause the user to receive information from the INTERLISP manual about the expression or command being typed. In the following example underlined characters were typed by the user. _(SETQ FOO (ELT 3 ?=C A = 3 N = (ELT 3 ?C elt[a;n] Value is nth element of the array a. elt generates an error, ARG NOT ARRAY, if a is not the beginning of an array. (ELT 3 ^W\\3 A 3] ? is also a programmer assistant command for use following an error. In many cases, the programmer's assistant can analyze the cause of the error (see example below). If not, the programmer's assistant simply presents information about the error from the manual. Example Most of the "basics" of on-line use of INTERLISP, e.g., defining functions, error handling, editing, saving your work, etc., are illustrated in the following brief console session. Underlined characters were typed by the user. 1. The user calls INTERLISP from Tenex, INTERLISP prints a date, and a 2.5 greeting. The prompt character _ indicates the user is at the top level of INTERLISP. 2. The user defines a function, fact, for computing factorial of n. In INTERLISP, functions are defined via DEFINE or DEFINEQ, (Section 8). Functions may independently evaluate arguments, or not evaluate them, and spread their arguments, or not spread them (Section 4). The function fact shown here is an example of an everyday run-of- the-mill function of one argument, which is evaluated. The function definition uses CLISP (Conversational LISP, Section 23). The CLISP will automatically be converted to LISP when the function is run. 3. The user "looks" at the function definition. Function definitions in INTERLISP are stored in a special cell called the function definition cell, which is associated with the name of the function (Section 8). This cell is accessible via the two functions, getd and putd, (define and defineq use putd). Note that the user typed an input consisting of a single expression, i.e., (GETD (QUOTE FACT)), which was therefore interpreted as a form for eval. The user could also have typed GETD(FACT). 4. The user runs his function. Two errors occur and corrections are offered by DWIM (Section 17). In each case, the user indicates his approval, DWIM makes the correction, i.e., actually changes the definition of fact, and then continues the computation. 5. An error occurs that DWIM cannot handle, and the system goes into a break. At this point, the user can type in expressions to be eval- ed or apply-ed exactly as at the top level. The prompt character ":" indicates that the user is in a break, i.e., that the context of his computation is available. In other words, the system is actually "within" or "below" the call to itimes in which the error occurred. 6. The user types in the break command, BT, which calls for a backtrace to be printed. In INTERLISP, interpreted and compiled code (see Section 18 for discussion of the compiler) are completely compatible, and in both cases, the name of the function that was called, as well as the names and values of its arguments are stored on the stack. The stack can be searched and/or modified in various ways (see Section 12). Break commands are discussed in Section 15, which also explains how the user can "break" a particular function, i.e., specify that the system go into a "break" whenever a certain function or functions are called. At that point the user can examine the state of the computation. This facility is very useful for debugging. 2.6 @LISPC 1 INTERLISP-10 11-17-73 ... GOOD EVENING. _DEFINEQ((FACT (LAMBDDA (N) (IF N=0 THEN NIL ELSE N*(FACTT N-1] 2 (FACT) _(GETD 'FACT) 3 (LAMBDDA (N) (IF N=0 THEN NIL ELSE N*(FACTT N-1)) _FACT(3) 4 LAMBDDA {IN FACT} -> LAMBDA ? YESC FACTT {IN FACT} -> FACT ? YESC NON-NUMERIC ARG 5 NIL IN ITIMES (BROKEN) :BTC 6 ITIMES COND FACT COND FACT COND FACT **TOP** :NC 7 1 :?C 8 BECAUSE ITIMES REQUIRES THAT EACH OF ITS ARGUMENTS BE A NUMBER BUT IN (ITIMES N (FACT (SUB1 N))) {IN FACT}, THE VALUE OF (FACT (SUB1 N)) IS NIL WHEN N=1 :EDITF(FACT) 9 EDIT *(R NIL 1) 10 *OKC 11 FACT :RETURN 1C 12 'BREAK' = 1 6 _PP FACTC 13 (FACT [LAMBDA (N) (COND ((EQ N 0) 1) (T (ITIMES N (FACT (SUB1 N]) FACT 14 _PRETTYDEF((FACT) FACT) 15 FACT.;1 2.7 7. The user asks for the value of the variable n, i.e., the most recent value, or binding. The interpreter will search the stack for the most recent binding, and failing to find one, will obtain the top level value from the atom's value cell, which is car of the atom (Section 3). If there are no bindings, and the value cell contains the atom NOBIND, an unbound atom error is generated (Section 16). 8. The user types ?, a command to the programmer's assistant (Section 22). The p.a. looks at the error and the context and using its information about ITIMES, "explains" the error. 9. The user realizes his error, and calls the editor to fix it. (Note that the system is still in the break.) The editor is described at length and in detail in Section 9. It is an extremely useful facility of INTERLISP. Section 9 begins with a simple introduction designed for the new user. 10. The user instructs the editor to replace all NIL's (in this case there is only one) by 1. The editor physically changes the expression it is operating on so when the user exits from the editor, his function, as it is now being interpreted, has been changed. 11. The user exits from the editor and returns to the break. 12. The user specifies the value to be used by itimes in place of NIL by using the break command RETURN. This causes the computation to continue, and 6 is ultimately returned as the value of the original input, fact(3). 13. The user prettyprints (Section 14) fact, i.e., asks it be printed with appropriate indentations to indicate structure. Prettyprint also provides a comment facility. Note that both the changes made to fact by the editor and those made by DWIM are in evidence. 14. The user writes his function on a file by using prettydef (Section 14), creating a Tenex file, FACT.;1, which when loaded into INTERLISP at a later date via the function load (Section 14), will cause fact to be defined as it currently is. There is also a facility in INTERLISP for saving and restoring an entire core image via the functions sysout and sysin (Section 14). 15. The user logs out, returning control to Tenex. However, he can still continue his session by re-entering INTERLISP via the Tenex REENTER or CONTINUE command. 2.8