home *** CD-ROM | disk | FTP | other *** search
Text File | 1986-08-13 | 204.1 KB | 9,188 lines |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cybermetrics PDLISP Language Manual
-
-
- Author: Dave Morein
-
-
- Document Version: 1.10
- Release Date: August 11, 1986
-
-
- Copyright (c) 1985, 1986 by Cybermetrics
- All rights reserved, worldwide.
-
-
- Published by
-
- Cybermetrics
- P.O. Box 1194
- Los Gatos, California 95031
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- TRADEMARK ACKNOWLEDGMENTS:
-
- MS-DOS is a trademark of Microsoft, Inc.
- UNIX is a trademark of ATT Bell Laboratories
- Intel is a trademark of Intel Corporation
- IBM and PC-DOS are trademarks of
- International Business Machines, Inc.
-
- All other product names are trademarks of their
- associated manufacturers/publishers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- About PDLISP, UNXLISP and Cybermetrics
-
- PDLISP and UNXLISP are products which I developed over the
- period of time from 1981 to the present. I am distributing
- binary copies of PDLISP for free through bulletin board
- systems (BBS's) to people who are interested in learning
- about LISP and artificial intelligence programming. UNXLISP
- is a commercial product, which I distribute through several
- dealers who are listed in the appendix to the manual called
- "product support."
-
- At the present time (August, 1986) both products are in a
- state of flux. PDLISP is distributed with a manual on an
- MS-DOS disk. UNXLISP is distributed with a printed manual,
- and contains some features which PDLISP does not. Most of
- these features are still a month or two away from being
- released. However, I provide free updates to purchasers of
- the commercial product.
-
- While neither product is "Common LISP" compatible at the
- present time, I am working hard in this direction. By
- sometime in 1987, I hope to have achieved Common LISP
- compatibility with UNXLISP. Free updates, of course, will be
- provided to all of my early customers.
-
- Anyone is free to copy this diskette as long as it is for
- personal use, and not commercial, and as long as it is not
- altered and all copyright messages are preserved.
-
- I am distributing PDLISP even though it is not my "primary
- income generating activity." In other words, I'm doing
- it for fun. My hope is that others will see them in the same
- light.
-
- - Dave Morein
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
-
-
-
-
- Chapter 1
-
- An Overview of LISP
-
-
-
- LISP is a language intended primarily for symbolic
- manipulation. It has been used for programming solutions to
- problems in computer science, the integral calculus, circuit
- theory, mathematical logic, question-answering systems,
- game-playing, and other fields of artificial intelligence
- research. LISP's versatility is probably unmatched in the
- field of programming languages.
-
- LISP differs radically from most other computer languages
- in two main respects. First, data is stored in LISP in what
- are known as symbolic expressions, or S-expressions for
- short. S-expressions are, abstractly, tree-structured
- constructs of variable length. In LISP, S-expressions are
- allocated automatically, so that the programmer is freed
- from the necessity of manually organizing storage for his
- variables. Secondly, in LISP there is no distinction
- between programs and data. LISP programs are just
- S-expressions which the user has specified to be executed.
- LISP programs can even produce programs in the form of data
- to be executed.
-
-
-
-
-
-
- 1.1 Symbolic Expressions
-
-
- Symbolic Expressions can exist in PDLISP in several
- forms, including atoms and lists. Atoms are the most
- primitive unit of data, corresponding to "words" in English.
- Lists are more abstract groups of data, roughly
- corresponding to "sentences" in English. They are used to
- group data to make it more convenient to manipulate and
- interpret it.
-
-
-
-
-
- - 1 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
- 1.1.1 Atoms and Lists
-
- As an initial definition, atoms in PDLISP are sequences of
- indefinite length composed of letters, digits, or a few
- other characters but not beginning with a digit. A more
- precise definition is given in the section entitled "The
- PDLISP Reader".
-
- For example, the following are legal atoms in PDLISP:
-
-
- A
- Thisisalongatom
- Thisisaverylongatom
- Thisisanevenlongeratom
- someatomsaretalented
- THX1138
-
- The following are not legal atoms in PDLISP:
-
-
- 234a - (does not begin with a letter)
- This is not an atom - (contains imbedded spaces)
- "I am not a legal string. - (no closing quote)
-
-
- 1.1.2 Reserved Words
-
- The following is a list of all of the reserved words in
- PDLISP. Any attempt to use one of these words as an atomic
- name will probably result in an error.
-
-
- BLOCK LEXPR T
- CDQ MACRO TAGBODY
- CNSUBR MCDQ UNBOUND
- CSUBR NIL VAR
- DEXPR NLAMBDA -
- FIN NSUBR +
- GLOBAL PUTD &AUX
- LAMBDA QUOTE &OPTIONAL
- LET SUBR &REST
- LET* SETQQ
-
-
-
-
-
-
-
-
- - 2 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
- 1.1.3 Numbers
-
- PDLISP currently supports fixed point ("integer") and
- floating point ("float") numbers. Floats carry can be input
- either in ordinary format (e.g., 423.7) or in scientific
- notation (e.g., 4.237E2). The following are legal PDLISP
- floats:
-
-
- 3.14159
- 6.02E23
- -1.02
- +5.6
- 4.29E-5
-
-
- 1.1.4 Quoted Strings
-
- Characters besides letters, digits, and a few others are
- not ordinarily permitted in PDLISP atoms. They can be
- included with the use of the double quote mark ("),
- however. For example, the following are perfectly good
- PDLISP atoms:
-
-
- "certain inalienable rights"
- "1962 was a very good year."
- "!#$`|%&'&'(()*:{}[]<>?+`"
-
- Lists are just groups of atoms which are surrounded by a
- balanced pair of parenthesis and separated by blank spaces.
-
- Here are some legal lists:
-
-
- (This is a list)
- (Fourscore and seven years ago)
- (Jimmie Ted and Ronnie)
- (some lists are talented)
-
- Here are some illegal (poorly formed) lists:
-
-
- (this one does not have a right parenthesis
- this one does not have a left parenthesis)
- this one does not have either
-
-
-
-
-
- - 3 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
-
-
- 1.2 The PDLISP evaluator
-
-
- In high school algebra, most people are exposed to the
- notion of a function. For example, when we write down a
- function named 'f' which adds 4 to its argument, we write
- f(x) = x + 4. Later on, if we should wish to apply this
- function f, we might write, for example, h = f(2).
-
- Things are similar in PDLISP. We can define functions and
- apply them to arguments by enclosing the name of the
- function along with its arguments in a set of parenthesis,
- thusly forming a list. For example, if we should wish to
- apply the function 'f' from the above example to the number
- 2, we would write:
-
-
- (f 2)
-
- The above s-expression constitutes what is known in LISP as
- a form because it can be evaluated. Evaluation is performed
- in PDLISP by another function, called eval. Normally, when
- the user logs into PDLISP, the interpreter prints out the
- prompt:
-
-
- /USR/LOGIN->
-
- The above prompt consists of a directory name which is the
- "/USR/LOGIN" part, and the right arrow, which is the "->"
- part. Directories will be covered in a later chapter, but
- for now, they can safely be ignored.
-
- The interpreter will wait until the user types in a valid
- s-expression, will then evaluate that expression, and
- finally print out the result onto the user's console. This
- is known as a READ-EVAL-PRINT loop. For example, assuming
- that the function 'f' had previously been defined as
- described above (more about that later), the following
- dialog might occur:
-
-
-
-
-
-
-
-
-
- - 4 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
- /USR/LOGIN->(f 2)
- 4
- /USR/LOGIN->(f 5)
- 7
-
- In order to allow the programmer to document his code,
- PDLISP ignores any input on a line after a semicolon (;).
- For example, we could have typed:
-
-
- /USR/LOGIN->(f 2) ;invoke f(2)
- 4
- /USR/LOGIN->(f 5) ;invoke f(5)
- 7
-
- Each time that the user types in a list which is a form
- (meaning that the evaluator can evaluate it), the system
- will print out the value of the expression which the user
- typed in, and then an "/USR/LOGIN->" prompt. The
- "/USR/LOGIN->" prompt means that the evaluator is ready for
- more input. If the user enters the form (EXIT), then the
- interpreter will exit to the operating system, as shown
- below:
-
-
- /USR/LOGIN->(exit)
- % ;(or some other operating system prompt,
- ; such as A> on MS-DOS).
-
-
-
-
- 1.3 The Pause which Refreshes
-
-
- If you purchased a version of PDLISP which contains what
- is called a "mark and sweep garbage collector", then you
- will find that occaisionally, the system pauses and appears
- to do nothing. Please be patient ! On a slow machine (IBM
- PC), this function can take six or seven seconds; on a fast
- machine, (IBM PC-AT), it will take about a third of that
- time. If you wish, you can set things up so that PDLISP
- beeps each time that it begins this function. For more
- information, consult the section on storage management
- functions.
-
-
-
-
-
-
- - 5 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
-
-
- 1.4 Assigning Values to Variables
-
-
- Suppose that in the above example where f(x) = x + 2, that
- we wished to assign a value to the variable x. That is,
- suppose we wish to say,
-
-
- let x = 3
-
- The way in which this would ordinarily be done in PDLISP
- would be through the use of the SETQ function. For example,
- one might enter the following:
-
-
- /USR/LOGIN->(setq x 3) ;sets x = 3
- 3 ;Now, we can apply f
- /USR/LOGIN->(f x) ;to the variable x.
- 5 ;f is as described previously.
-
- A form containing SETQ is evaluated just like any other
- form, and it even returns a value of 5 in this case.
- However, unlike our function f, it also has a side effect,
- which is another way of saying that it does something
- besides returning a value. In this case, SETQ binds the
- value 3 to the variable x. From now on, unless we apply
- SETQ to x again, x will have a value of 3. In fact, as the
- following dialog with PDLISP demonstrates, x can be
- evaluated as a form:
-
-
- /USR/LOGIN->x
- 3
-
- Functions can also take more than one argument, as in the
- case of some function 'g' of two arguments. For example,
- let g(x,y) be defined as x + y. Then the following dialog
- might occur:
-
-
-
-
-
-
-
-
-
-
-
- - 6 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
- /USR/LOGIN->(g 3 2)
- 5
- /USR/LOGIN->(setq x 1)
- 1
- /USR/LOGIN->(setq y 2)
- 2
- /USR/LOGIN->(g x y)
- 3
-
- It should be noted that as in the above examples, a form in
- LISP consists of two parts: a function name and an argument
- list. For example, when the interpreter evaluated the form
- (g x y), g was the function name, and x and y constituted
- the argument list of the form.
-
- Generally speaking, as in the above examples, the
- interpreter (or the "evaluator" for short) reads an
- s-expression from the console, prints out the value of that
- s-expression, and then loops around again, until the user
- enters invokes the EXIT function as follows:
-
-
- /USR/LOGIN->(exit)
- % ;host operating system prompt.
-
- We are ready to make what is called a 'recursive
- definition' of the term 'symbolic-expression.' A recursive
- definition is a mathematical term for a definition which is
- expressed in terms of itself. For example, suppose that we
- wished to describe the set of all positive integers to a
- stranger from Mars. We could start by saying "0, 1, 2, 3, 4,
- ...", but the stranger would surely run out of patience
- before we had enumerated all of the positive integers, and
- we might find ourselves getting cooked by a ray gun. Or we
- could say the following:
-
-
- (1) "0 is a positive integer"
- (2) "a number is a positive integer if it is equal
- to the sum of 1 and a positive integer"
- (3) "a number is a positive integer if and only if
- it is compelled to be one by conditions (1)
- and (2) stated above."
-
- Given the above definition of a positive integer, we could
- write what is called a recursive algorthm which decides
- whether or not a given number is a positive integer. An
- algorithm is a well-defined procedure of steps which even a
-
-
-
- - 7 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
- computer can follow which eventually terminates.
-
-
- In English, here is the algorithm:
-
- step 1: if the number is 0, then stop with a positive
- integer recognized;
- step 2: if the number is less than 0, then stop with
- a number which has been determined not to be
- a positive integer;
- step 3: otherwise, our number is a positive integer
- if and only if this algorithm determines that
- the number minus 1 is a positive integer.
- So, start over again at step 1, with our
- number diminished by 1.
-
- The above algorithm is recursive, because if it cannot
- immediately determine in step 1 or step 2 whether the number
- is a positive integer, it calls itself with a new argument.
-
- Likewise, we can give a recursive definition of a
- symbolic-expression:
-
-
- (1) An atom is a symbolic expression.
- (2) A list of the form
- (<s-expr> <s-expr> ... <s-expr>)
- is a symbolic expression if and only if each of
- the <s-expr> constructs is a symbolic expression.
- (3) Nothing is a symbolic expression unless it is
- compelled to be one by (1) and (2) above.
-
- What we are actually saying here is that a string of symbols
- is defined to be a symbolic expression if and only if it is
- either an atom or a list of symbolic expressions.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 8 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
-
-
-
- 1.5 Parenthesis Counting
-
-
- PDLISP also keeps track of how many parenthesis need to be
- matched in the current expression being entered. For
- example, instead of entering:
-
-
- /USR/LOGIN->(setq a 4)
- 4
-
- one could have entered the same expression on different
- lines, as in the following:
-
-
- /USR/LOGIN->(
- 1 ->setq
- 1 -> a
- 1 ->4
- 1 ->)
- 4
-
- The "1 ->" part of each line was printed out by PDLISP to
- indicate the number of right parenthesis which would be
- necessary to complete the expression being entered. The
- primary reason for this additional bit of interaction is to
- prevent us from prematurely concluding that we have entered
- a complete symbolic expression while the interpreter sits
- waiting for us to finish the job. This feature is called
- parenthesis counting.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 9 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 10 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual An Overview of LISP
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 11 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
-
-
-
-
- Chapter 2
-
- Some System Primitives
-
-
-
- In this chapter we will examine a set of functions which
- are called primitives because they are supplied with the
- PDLISP interpreter and do not have to be written by the
- user. They constitute the basic 'building blocks' out of
- which we will be able to construct useful programs.
-
-
-
-
- 2.1 Some Primitive Functions
-
-
- Besides being able to work with numbers, LISP has a number
- of primitive functions designed to work on the structure of
- symbolic expressions. For example, consider a list like
-
-
- (SMALL COMPUTERS ARE FRIENDLY)
-
- One might want to pick off the first element of the above
- list leaving
-
-
- (COMPUTERS ARE FRIENDLY)
-
- or one might wish to add an element to the front of the
- list, resulting in the list:
-
-
- (FAST SMALL COMPUTERS ARE FRIENDLY)
-
- In this section we shall examine the built-in functions
- provided with PDLISP (and most other LISP dialects) for
- doing such things. Their names are strange; Some of the
- basic ones are called CAR, CDR, APPEND, LIST, and CONS. It
- may seem that functions with names like CAR and CDR must
- have come from another planet. That is nearly correct; they
- came from Boston.
-
-
-
- - 12 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
-
-
- 2.1.1 CAR and CDR
-
- CAR returns as its value the first element of a list. For
- example, if we were sitting down at the computer, the
- following dialog could occur:
-
-
- /USR/LOGIN->(car '(small computers are friendly))
- SMALL
- /USR/LOGIN->(car '(a little boat plied the seas))
- A
-
- In the following example, the argument given to CAR is the
- two-element list ((once in a) while). The first element of
- this list is also a list, (once in a), and since it is the
- first element of the argument, CAR returns it:
-
-
- /USR/LOGIN->(car '((once in a) while)
- (ONCE IN A)
-
- CDR does exactly the opposite of what CAR does. It returns
- a list containing everything but the first element.
-
-
- /USR/LOGIN->(cdr '(small computers are capable))
- (COMPUTERS ARE CAPABLE)
- /USR/LOGIN->(cdr '(a b c))
- (B C)
-
- One important distinction between CAR and CDR is that while
- CAR may sometimes return an atom, CDR always returns a
- list. For example, (car '(a b c)) would result in A, which
- is an atom, but (cdr '(a b c)) would result in (B C), which
- is a list. CAR extracts the element A from the argument
- list, whereas CDR moves the parenthesis over the first
- element of the list and deletes it. In fact, as the
- following conversation illustrates, a very curious
- phenomenon occurs when CDR is presented with certain
- arguments:
-
-
- /USR/LOGIN->(cdr '(a))
- NIL
-
- What is happening? Did we supply CDR with a list and get
-
-
-
- - 13 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- back an atom? Well, the answer is yes and no. What we got
- back is a very special atom in the LISP system, called NIL.
- NIL is simultaneously an atom and a list. The list is
- called the empty list, and it is written as (). Whenever the
- PDLISP interpreter prints out an empty list, it prints out
- the name of the atom NIL. When we supplied (A) to CDR, it
- moved the left parenthesis over the first element of the
- argument list, resulting in (). Then, when it came time for
- PDLISP to print out (), it printed out NIL. NIL and () are
- completely equivalent in every respect, and they are
- represented identically internally.
-
- One should note that CAR and CDR both take lists as
- arguments. If either function is invoked with an atom as an
- argument, it will return an error message. This is natural,
- because the jobs of CAR and CDR are to divide a list into
- two parts and to return one of them. Since an atom is by
- definition an indivisible unit, it cannot be divided into
- two parts. The following dialog with PDLISP illustrates
- this fact:
-
-
- /USR/LOGIN->(car 'A)
- ***> CAR: arg is atomic. ;evaluation causes error
- /USR/LOGIN->(cdr 'A)
- ***> CDR: arg is atomic.
- /USR/LOGIN->
-
- NIL is the only atom which is a legal argument for CAR
- and CDR. That is, (CDR 'NIL) ==> NIL, and (CAR 'NIL) ==> NIL.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 14 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- Here, we are using the symbol "==>" as an abreviation for
- the phrase "evaluates to." I will use this symbol in the
- rest of this manual, as well as the related symbol, "<==>",
- which means "is equivalent to." By "equivalent to", I mean
- that two expressions evaluate to the same value. That is, I
- will write A <==> B whenever the evaluation of A equals the
- evaluation of B.
-
- [1]
-
-
-
-
- 2.1.2 Quote Marks and the Evaluator
-
- I will now explain those funny little quote marks which have
- been appearing in symbolic expressions. Suppose that we
- wish to find the first element of a list by using CAR, and
- type in the following s-expression:
-
-
- /USR/LOGIN->(car (a b c))
- ***> APPLY: function A is UNBOUND. ;function APPLY inside the
- ;interpreter complains.
-
- What happened? It may seem that the meaning of the
- s-expression (CAR (A B C)) is perfectly obvious: namely, to
- return the first element of the list (A B C). However, LISP
- does not quite see things that way. In evaluating
- (CAR (A B C)), the interpreter goes through the following
- process:
-
- First it checks to see if the form is a list or an atom.
- Since it is a list, the interpreter assumes that the first
- element of the list is a function name, which in this case
- is CAR. Next, since CAR is defined as a function which wants
- its arguments to be evaluated, the interpreter evaluates
- (A B C). However, this is where it encounters a problem.
- (A B C) is evaluated just as any other form would be, so the
- interpreter assumes that the first element, A, is the name
- of a function. Since A is not defined as a function, an
- error message is output.
-
-
- ----------
-
- 1. More precisely, A <==> B means that the evaluation of A
- is EQ to the evaluation of B, where EQ is a LISP function
- which tests for a particular form of equality. This notion
- is covered more fully in the section on equality functions.
-
-
-
- - 15 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- The problem in the above example, aside from the fact that
- the computer tried to do exactly what we told it to do, is
- that we need a way to supply literal arguments to
- functions. That is, we need a way to turn off the evaluator
- at some point in its computation, so that instead of trying
- to evaluate (A B C), it merely accepts (A B C) as a literal
- argument to CAR. Fortunately, there is such a way. It is
- called the QUOTE function.
-
- The QUOTE function is a function of one argument, which
- may be a list or a single atom, which returns the value of
- its argument. For example,
-
-
- /USR/LOGIN->(quote (a b c))
- (A B C)
- /USR/LOGIN->(car (quote (a b c)))
- A
-
- Quote performs the useful function of telling the
- interpreter to turn off the evaluator inside an
- s-expression, so that we can supply literal arguments to
- functions. Since the word "quote" is so cumbersome, an
- alternative notation has been developed. Typing '(a b c) is
- the same as typing (quote (a b c)) as far as the interpreter
- is concerned. Both expressions are converted to the same
- internal form, and they are evaluated identically. For
- example,
-
-
- /USR/LOGIN->(quote (a b c))
- (A B C)
- /USR/LOGIN->'(a b c)
- (A B C)
- /USR/LOGIN->(car (quote (a b c)))
- A
- /USR/LOGIN->(car '(a b c))
- A
-
-
- 2.1.3 Auto-Quoting Functions and Atoms
-
- Some PDLISP functions have the property of automatically
- quoting some or all of their arguments. For example, the
- SETQ function, which we have already observed, quotes its
- first argument. There is another, equivalent function,
- called SET, which does the same thing as SETQ without the
- auto-quoting.
-
-
-
-
-
- - 16 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- /USR/LOGIN->(set 'a 'b)
- B
- /USR/LOGIN->(setq a 'c)
- C
-
- One should note that in the above dialog, SETQ does not
- quote its second argument; only the first one is quoted.
- The second argument must be quoted manually to keep the
- evaluator from evaluating it as a separate s-expression.
-
- Some atoms are automatically quoted. For example, numbers
- are always auto-quoted. That is, normally when an atom name
- is entered, no value is associated with it until the
- variable is bound by a SET or SETQ. However, numbers are
- always bound to themselves automatically, and a call to SET
- or SETQ with a number as the first argument will result in
- an error:
-
-
- /USR/LOGIN->3
- 3
- /USR/LOGIN->(set 3 '4)
- ***> SET: first arg cannot be a number.
- /USR/LOGIN->
-
- Numbers and strings in PDLISP are constants in that their
- value can never be changed by a call to SET or SETQ. Quoting
- a number or a string, by the way, has no effect, since
- quoting just returns the number or string (which is equal to
- its value).
-
- There are also symbolic constants in PDLISP. Any reserved
- word (see section 1.1.2) evaluates to itself. Of these, the
- most important are the symbols T and NIL. That is,
- (eval T) ==> T, and (eval NIL) ==> NIL.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 17 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
- 2.1.4 CONS and CONSP
-
- CONS stands for "list CONStructor". It creates a new cell
- which is a "dotted pair" of its two arguments. For example,
-
-
- (cons 'a 'b) ==> (a . b)
- (cons 'a '(b c d e)) ==> (a b c d e)
- (cons 'nil 'nil) ==> (nil . nil)
-
- Because non-atomic cells can only be created by the CONS
- function, such cells are often called cons cells.
-
- CONSP is a function of one argument which returns T if and
- only if its argument is a cons cell. For example,
-
-
- (consp 'a) ==> NIL
- (consp '(a b)) ==> T
- (consp 'nil) ==> NIL
- (consp '()) ==> NIL
-
- In the above examples, NIL is treated as an atom, and not as
- a list. This is purely a matter of convention, and things
- could have wound up being the other way around.
-
-
-
-
- 2.1.5 APPEND
-
- APPEND is a built-in primitive function which produces a
- list out of the elements of its arguments (which must be
- lists). For example,
-
-
- /USR/LOGIN->(append '(LISP is an) '(interactive language))
- (LISP IS AN INTERACTIVE LANGUAGE)
- /USR/LOGIN->(append '(LISP) '(is an interactive language))
- (LISP IS AN INTERACTIVE LANGUAGE)
- /USR/LOGIN->(append '(LISP) '(is an) '(interactive language))
- (LISP IS AN INTERACTIVE LANGUAGE)
- /USR/LOGIN->(append '() '(LISP is an interactive language))
- (LISP IS AN INTERACTIVE LANGUAGE)
- /USR/LOGIN->(append 'nil '(LISP is an interactive language))
- (LISP IS AN INTERACTIVE LANGUAGE)
-
-
-
-
-
- - 18 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
- 2.1.6 LIST
-
- LIST is a function which is similar to APPEND except that
- instead of combining the elements of its arguments into a
- list, LIST produces a list of its arguments. For example:
-
-
- /USR/LOGIN->(list '(LISP is an) '(interactive language))
- ((LISP IS AN) (INTERACTIVE LANGUAGE))
- /USR/LOGIN->(list '(LISP) '(is an interactive language))
- ((LISP) (IS AN INTERACTIVE LANGUAGE))
- /USR/LOGIN->(list '(LISP) '(is an) '(interactive language))
- ((LISP) (IS AN) (INTERACTIVE LANGUAGE))
- /USR/LOGIN->(list 'LISP '(is an interactive language))
- (LISP (IS AN INTERACTIVE LANGUAGE))
- /USR/LOGIN->(list '() '(LISP is an interactive language))
- ((LISP IS AN INTERACTIVE LANGUAGE))
- /USR/LOGIN->(list 'nil '(LISP is an interactive language))
- ((LISP IS AN INTERACTIVE LANGUAGE))
-
-
- 2.1.7 REVERSE
-
- REVERSE simply constructs a new list which is the reversal
- of its single argument, which must be a list. For example,
-
-
- (reverse '(a b c)) ==> (c b a)
- (reverse '()) ==> ()
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 19 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
-
-
- 2.2 Some Useful Predicates
-
-
- Predicates are functions which only return T or NIL. What
- follows is a survey of the most common ones.
-
-
- 2.2.1 ATOM and SYMBOLP
-
- ATOM returns T if (and only if) its argument is atomic. It
- should be noted that there are several types of atoms:
-
-
- - floating point numbers, such as 3.14159 and 6.02E+23
-
- - integers, such as 2, 3, and 5
-
- - strings, such as "I am not a crook."
-
- - variables and functions, such as CAR, CDR, and CONS.
-
- Of the four types of atoms, only the last type have names.
- They are called symbols, and PDLISP maintains a table of
- them called the symbol table, which is also sometimes called
- the object list.
-
- Symbols can be identified with the SYMBOLP predicate. For
- example, (SYMBOLP 'A) ==> T, whereas (SYMBOLP 3.14) ==> NIL.
-
-
-
-
- 2.2.2 EQ, EQL, and EQUAL
-
- This group of predicates is used to determine equality
- between s-expressions. EQUAL is the most general predicate,
- and the novice should stick to it in preference to the other
- ones. EQ and EQL are special purpose predicates which
- presume some knowledge on the part of the programmer about
- the way that s-expressions are stored internally. More
- information about these functions is contained in the
- section on equality later in this chapter.
-
-
-
-
-
-
-
- - 20 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- 2.2.3 NULL
-
- NULL is a function of 1 argument which returns T if its
- argument evaluates to NIL, and T otherwise. e.g.,
- (NULL 'a) ==> NIL, (NULL 'NIL) ==> T, (NULL T) ==> NIL
-
-
- 2.2.4 NUMBERP
-
- NUMBERP returns T if its argument is a number (either a
- float or an integer). For example, (NUMBERP 1) ==> T,
- (NUMBERP 2.6) ==> T, and after (SETQ A 6), (NUMBERP A) ==> T
-
-
- 2.2.5 ZEROP
-
- ZEROP is a function which returns T if its argument is a
- number and is equal to 0. Otherwise, ZEROP returns NIL. For
- example, (ZEROP 0) ==> T, (ZEROP 1) ==> NIL, and after
- (SETQ A 0), (ZEROP A) ==> T
-
-
- 2.2.6 EVAL and explicit evaluation
-
- EVAL allows us to explicitly invoke the evaluator. For
- example,
-
-
- /USR/LOGIN->(setq a 4)
- 4
- /USR/LOGIN->a
- 4
- /USR/LOGIN->(eval 'a)
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 21 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
-
-
- 2.3 Internal Representation of Symbolic Expressions
-
-
- Comprehension of the material in this section is not
- absolutely necessary to be able to use LISP, but it is
- likely to be helpful. In particular, knowing how
- s-expressions are represented inside of the machine enables
- one to have a better idea as to "what is actually going on
- in there" when lists are being manipulated.
-
- S-expressions are, in principle, composed of two types of
- elements: nodes and atoms. Atoms are primitive objects,
- such as variables, numbers, and strings. Lists are built
- out of nodes, which "hold the list together", and the
- objects which are elements of the list. These elements
- could be atoms or other lists. To explain how symbolic
- expressions are represented inside a computer memory, I am
- introducing the concept of memory cells. Computer memory is
- organized as an array of cells. Each cell can hold a number,
- and each cell has an address, which is also a number. When
- the computer memory is presented with the address of a cell,
- the contents of the cell can be read out, or they can be set
- to a new value.
-
-
-
-
- 2.3.1 Nodes and Lists
-
- Nodes permit the construction of lists of atoms or of other
- lists. Here's what they look like:
-
-
- -------------------------
- | car cell | cdr cell |
- -----+------------+------
- | |
- | |
- | +-------> to some s-expression
- +--------------------> to some s-expression
-
- Each node consists of two cells, which are just pointers to
- some other cell in memory. The first cell in each node is
- called the "CAR pointer", or "CAR field", and the second
- cell is called the "CDR pointer" or the "CDR field." By
- pointer, I mean that the contents of the cell are used as an
-
-
-
- - 22 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- address of some other location in memory. So, when I say
- that cell A "points" to cell B, the implicit assumption is
- that the address of cell B is contained in the cell A.
-
- Because of the boxlike nature of my pictures of nodes and
- memory cells, I shall refer to my diagrams as box notation.
-
- The nodes which I have been discussing are often called
- cons cells, because they can only be created via the CONS
- function. A list is represented inside the LISP system by a
- very specific arrangement of cons cells, whereby each
- element of the list is pointed to by the CAR field of one
- cons-cell, and the list is joined together by the CDR field
- of each cons-cell. One could represent a list on paper as
- follows:
-
-
- --------------------- ---------------------
- | car cell | cdr cell | +-->| car cell | cdr cell |
- -----+----------+---- | -----+----------+----
- | | | | |
- | +------+ | +---> to next
- | | cons-cell
- | | in list
- | |
- +-----> to 1st element +-----> to 2nd element
- of list of list
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 23 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- In the above diagram, the cdr cell of the last cons-cell in
- the list points to NIL, which is a pre-defined memory
- location in the PDLISP system. Thus, the representation of
- a list contains one cons-cell for each element in the list.
- The elements of a list could be symbols, numbers, or other
- lists.
-
-
-
-
- As an example of a list, consider the s-expression (A B C).
- It could be represented in box notation as:
-
- -----------
- | car | cdr |
- --+-----+--
- | | -----------
- | +---->| car | cdr |
- | --+-----+--
- +---> A | | -----------
- | +---->| car | cdr |
- | --+-----+--
- +---> B | |
- | +----> NIL
- |
- +---> C
-
- The above list is terminated by a pointer to NIL, which is a
- built-in symbol. Notice that there is exactly one cons-cell
- for each element of the list.
-
-
-
-
- 2.3.2 Dotted Pairs
-
- Not all s-expressions can be printed as lists. For this
- reason, a more comprehensive notation has been developed,
- called "dotted pair notation." In essence, a dotted pair is
- a representation of a single cons cell, and consists of the
- following elements, in order:
-
-
- (1) a left parenthesis
- (2) the dotted pair representation of the CAR of the cons cell
- (3) a dot (".")
- (4) the dotted pair representation of the CDR of the cons cell
- (5) a right parenthesis
-
-
-
-
-
- - 24 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- For example, consider the following two s-expressions in box
- notation:
-
-
- expression # 1:
-
- -----------
- | car | cdr |
- --+-----+--
- | | -----------
- | +---->| car | cdr |
- | --+-----+--
- +---> A | |
- | +----> NIL
- |
- +---> B
-
-
- expression # 2:
- -----------
- | car | cdr |
- --+-----+--
- | |
- | +------> B
- |
- +------------> A
-
- The reader should recognize the first expression as being
- the list, (A B). The second expression, however, cannot be
- written as a list. According to the rules of dot notation
- as stated above, one would write it as "(A . B)", using the
- dot to separate the two halves of the cons cell.
-
- Because dotted pair notation is defined for every cons
- cell, all s-expressions can be written as dotted pairs. In
- particular, one can write all lists as dotted pairs. For
- example, the following pairs of s-expressions are
- equivalent:
-
-
- (A) <==> (A . NIL)
- (A B) <==> (A . (B . NIL))
- (A B C) <==> (A . (B . (C . NIL)))
-
-
-
-
-
-
-
-
-
-
- - 25 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
- 2.3.3 Atoms and Symbols
-
- An atom is an indivisible element which cannot be further
- decomposed using the LISP primitives CAR and CDR. As noted
- above, there are four types of atoms in PDLISP: integers,
- floats, strings, and user-defined atoms (symbols). Symbols
- are stored uniquely in the system. That is, two references
- to the same symbol name will be interpreted by PDLISP as
- being references to the same symbol. LISP interpreters do
- this by maintaining a symbol table of all of the symbols
- which they have encountered, which is also sometimes called
- the object list. Whenever a symbol name is read in from the
- console (or a file), the symbol table is first checked to
- see if a symbol by the same name already exists. If one
- does, then the symbol being read in is interpreted as being
- a reference to the one already in the system. Otherwise, a
- new entry is created which corresponds to the new symbol
- name. The process of creating a new symbol is called
- internment, and a symbol which has been placed in the symbol
- table in this manner is said to be "interned."
-
-
- 2.3.4 Symbolic Structure
-
- Here is a little diagram which depicts the internal
- structure of a symbol in PDLISP:
-
-
-
- ----------------
- | print-name +-----------> to name of the atom
- ----------------
- | variable cell +-----------> to variable value
- ----------------
- | function cell +-----------> to function value
- ----------------
- | property list +-----------> to property list
- ----------------
-
- A symbol can be thought of as a structure of four "cells."
- Each cell contains the address of a memory location in the
- memory space of the host computer where the associated
- information is stored. These cells are:
-
-
-
-
-
-
-
-
- - 26 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
-
-
- (1) The print-name cell, often called the pname cell by
- some authors. This cell points to the beginning of a
- string in the memory space of the host machine. It is
- set to a meaningful value when a symbol is read in by
- the interpreter, and it is rarely changed during execution.
-
- (2) The variable cell, often referred to as the value cell
- by some authors, contains the value of the symbol when
- it is being used as a variable. This cell can be manip-
- ulated using the SET and SETQ functions.
-
- (3) The function cell contains a pointer to an s-expression
- which represents the function definition of the symbol
- when it is being used as a function. This cell can be
- acessed and set using the GETD (or SYMBOL-FUNCTION) and
- PUTD functions.
-
- (4) The plist cell points to the beginning of the property
- list for this symbol. For more information, consult
- the chapter about property lists.
-
- The important thing to note about how symbols are stored
- in LISP is that a symbol can be defined as both a variable
- and as a function. When evaluating an s-expression, the
- interpreter decides which value to use depending upon the
- position of the reference to the symbol in the expression.
- For example, in evaluating the expression (FOO A B), the
- symbol FOO would be interpreted as a function. But if we
- just typed in the symbol FOO, the interpreter would look up
- the value cell of the symbol FOO and return that value.
-
-
-
-
- 2.3.5 Unique Representation and Equality
-
- Unlike other lisp objects, symbols are represented uniquely
- in PDLISP; that is, two references to the same symbol name
- refer to the same object. Other types of atoms (such as
- numbers and strings) are not stored uniquely. For example,
- if the number 4 were read in twice, it would be represented
- internally in two different places. Cons cells, as would be
- used to represent lists or dotted pairs are never
- represented uniquely. For example, if the list (A B C) were
- read in twice, it would be represented twice. The symbols
- A, B, and C would only be represented once, however.
-
- Several different functions which test for equality are
-
-
-
- - 27 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- provided with PDLISP (and Common LISP). They are EQUAL,
- EQL, and EQ.
-
-
-
-
- The most general of these is EQUAL. EQUAL sees equality as most
- people see it. When comparing symbols, EQUAL returns T if and only
- if both of its arguments are the same symbol. For example,
-
- (EQUAL 'A 'A) ==> T
- (EQUAL 'A 'B) ==> NIL
-
- When comparing strings, EQUAL returns T if the two strings have
- the same contents, even though strings are not stored uniquely.
- For example,
-
- (EQUAL "this is a string" "this is a string") ==> T
-
- When comparing numbers, EQUAL returns T if the two numbers
- are of the same type (integer or float) and if their arithmetic
- difference is 0. So,
-
- (EQUAL 9 9) ==> T
- (EQUAL 9 9.0) ==> NIL
- (EQUAL 0 0.0) ==> NIL
-
- When comparing conses (lists or dotted pairs), EQUAL calls itself
- recursively to obtain a solution. In particular, if X and Y are
- two conses, then (EQUAL X Y) evaluates to T if (CAR X) is EQUAL to
- (CAR Y), and (CDR X) is EQUAL to (CDR Y). So,
-
- (EQUAL '(A B) '(A B)) ==> T
- (EQUAL '(A . B) '(A . B)) ==> T
- (EQUAL '(A B) '(A C)) ==> T
- (EQUAL '(A (B . C)) '((B . C) A)) ==> NIL
-
- EQ is a much simpler function; it returns T if its two arguments
- point to the same lisp argument. For example,
-
- (EQ 'A 'A) ==> T
- (EQ 4 4) ==> NIL ;numbers not stored uniquely
- (EQ '(A B) '(A B)) ==> NIL ;neither are conses
- (EQ "a string" "a string") ==> NIL ;or strings
-
- EQL is intermediate in complexity (and usefulness) between EQ
- and EQUAL. It compares symbols, strings, and numbers as EQUAL
- does, but it does not call itself recursively to compare conses.
- For example,
-
-
-
-
- - 28 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Some System Primitives
-
-
-
-
- (EQL 'A 'A) ==> T
- (EQL 4 4) ==> T ;numbers are equal, of same type
- (EQL 4 4.0) ==> NIL ;numbers are not of the same type
- (EQL "a string" "a string") ==> T ;EQL examines strings...
- (EQL '(A B) '(A B)) ==> NIL ; but not conses.
-
-
-
-
- 2.4 Exercises
-
-
-
- 2.1 - Implement a function OUR-EQUAL which performs exactly
- like EQUAL. This function should be implemented in
- terms of itself, EQ, and EQL.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 29 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
-
-
-
-
- Chapter 3
-
- User-Defined Functions
-
-
-
- In LISP, a symbolic expression which is a list is always
- interpreted as being a function followed by a list of
- arguments. For example, the symbolic expression "(FN ARG)"
- would be interpreted by PDLISP as a function of one
- argument. If the expression were "(FN)", then PDLISP would
- interpret it as a function of zero (no) arguments.
-
- Likewise, an s-expression which consists of just the name
- of a symbol, such as "X" would be interpreted by PDLISP as
- being the contents of the variable cell of the symbol.
-
- For example, consider the following conversation with
- PDLISP:
-
-
- /USR/LOGIN->(setq a 4) ;setting a variable to a value.
- 4 ;PDLISP echoes the value.
- /USR/LOGIN->a ;evaluate A as a variable.
- 4 ;PDLISP prints A's value cell.
- /USR/LOGIN->(a) ;let's say we erroneously entered this.
- ***> APPLY: function A is UNBOUND ;error for unbound function.
-
- A form in PDLISP is a symbolic expression (or
- "s-expression") which can be evaluated. An symbol name is a
- form if it is defined as a variable. Another type of form
- can be represented as:
-
-
- (fn arg1 arg2 ... argn)
-
- where fn is some function which has been previously defined,
- and arg1, arg2, etc. are its arguments. Let's consider the
- following s-expression:
-
-
- (f a b)
-
- If f is a defined function, and a and b are defined
-
-
-
- - 30 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- variables, then (f ab) is called a "form" , because it is an
- s-expression which can be evaluated. Suppose, for the sake
- of argument, that f has been previously defined as the
- function which adds its arguments together. Suppose also
- that a and b have already been defined as variables using
- the SETQ function as described above. Then the interpreter
- would evaluate (f a b) as follows:
-
- The first thing that the interpreter notices is that
- (f a b) is a list. Consequently, it can infer that the form
- is composed of two parts, namely, a function and an argument
- list. At this point, UNXLISP breaks up the form into these
- two parts, which are:
-
-
- part 1 = f, part 2 = (a b)
-
- The next thing that PDLISP does is to evaluate each element
- of the argument list. Let's assume that a and b have been
- previously defined, using SETQ, as the integers 1 and 2,
- respectively. Then parts 1 and 2 would be:
-
-
- part 1 = f part 2 = (1 2)
-
- Part 2 is now the evaluated argument list. PDLISP now
- applies the part 1, f to part 2, (1 2). Without delving any
- deeper into the interpreter, the result is 3.
-
- The relevance of all of this to function definition is
- that when the interpreter looked up the value of f, it
- looked in a different place than when it looked up the
- values of a and b. When looking up the value of f, PDLISP
- examined the "function cell" for the symbol f. When looking
- up the values of a and b, PDLISP examined the "variable
- cells" of a and b.
-
-
-
-
-
-
- 3.1 Defining Functions
-
-
- The easiest way to define a function in PDLISP is to use
- the DEFUN form, which uses a syntax similar to the one used
- in conventional mathematics. For example, if we wished to
- define a function, FOO, of one argument, X, as the sum of X
- and 1, we could write:
-
-
-
- - 31 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
- (defun foo (x) (+ x 1))
-
- The following are illustrations of the usage of DEFUN:
-
-
- (defun foo (x y) (+ x y))
- (defun bar (x) (* x (foo x)))
- (defun foobar (x) (+ (foo x) (bar x)))
-
- DEFUN itself is defined in terms of the DEF function, which
- is in turn defined in terms of the primitive function PUTD.
- PUTD is called a "primitive" because it is essentially
- built-in to PDLISP; it is defined as a machine-language
- routine, and is not defined in terms of anything else.
-
- DEFUN returns as its value the name of the function which
- was just defined.
-
-
-
-
-
-
- 3.2 DEF and PUTD
-
-
- The following material is provided for those who wish to
- have a deeper understanding of how functions are defined in
- PDLISP, and who wish to understand LAMBDA's, NLAMBDA's, and
- MACRO's.
-
- Functions in PDLISP are defined using PUTD in a way
- similar to the way that variables are assigned a value by
- SET, except that instead of setting the value cell of the
- symbol, PUTD sets its function cell. PUTD returns as its
- value the new value of the function cell. The function DEF
- behaves the same way as the built-in function PUTD, except
- that it returns the name of the argument which was defined.
-
- First, let us define a function in the language of
- high-school algebra. Let us say that we wish to define a
- function 'g' of one variable which adds 3 to that variable.
- Then we might write:
-
-
- let g (x) = x + 3
-
- The part of the above statement to the right of the '=' sign
-
-
-
- - 32 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- corresponds to a LISP form because, assuming that we know
- ahead of time what the value of x is, we can properly
- evaluate the value of 'x + 3'. Taken as a whole, the
- statement constitutes a definition, because we have defined
- g in terms of an evaluable form. The variable 'x' in the
- above example is called a dummy variable because it has no
- meaning except as a 'place holder' for our definition
- purposes. In LISP, we would call x a bound variable.
-
- To write the same statement in PDLISP, let us break the
- problem down into 2 parts: let us write first the right-hand
- side of the definition, and then the entire thing.
-
-
- To encode the 'x + 3' part, we would write:
-
- (+ x 3)
-
- To encode the entire statement 'let g (x) = x + 3'
- we would write:
-
- (def g (lambda (x) (+ x 3)))
-
- We are actually setting the function cell of g, which is an
- s-expression, to be the value (lambda (x) (+ x 3)), another
- s-expression, which is called the lambda expression. For
- now, it might be profitable to think of the word 'LAMBDA' in
- LISP as meaning 'is a function of'. After having defined g
- as in the above example, we can verify and manipulate its
- value as follows:
-
-
- ;
- ; let's start by defining a function:
- ;
- /USR/LOGIN->(def g (lambda (x) (+ x 3)))
- G ;returns name of the function.
- /USR/LOGIN->(getd 'g) ;get contents of function cell.
- (LAMBDA (X)(+ X 3)) ;it's a lambda-expression.
- /USR/LOGIN->(car (getd 'g)) ;we can get the
- LAMBDA ;head of the lambda form
- /USR/LOGIN->(cdr (getd 'g)) ;
- ((X) (+ X 3)) ; ...and the tail.
-
-
-
-
-
-
-
-
-
-
- - 33 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
-
-
- 3.3 Lambda Binding
-
-
- Lambda binding, as occurs with the parameters of a function,
- is different in its effects than assignment, as performed by
- SETQ. With SETQ, the previous value of the variable being
- assigned a value is discarded, and is no longer available.
- However, with lambda binding, the previous value is saved
- away somewhere, and upon exiting the lambda-expression, the
- old value is restored. A more succint way of saying this is
- that each lambda-variable has a scope, where its value
- "makes sense." When the scope of the lambda-expression is
- exited, then the lambda-variables no longer have any
- meaning.
-
- The set of symbols and their bindings is often called an
- environment. Each time that a function is entered, the
- environment is altered to reflect the new values of the
- lambda-variables which were bound. This event is called a
- lambda-binding transaction, since it is usually best thought
- of as an indivisible event. After the function is exited,
- of course, the environment is restored as the
- lambda-variables are rebound to their entry values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 34 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
-
-
- 3.4 NLAMBDA's
-
-
- NLAMBDA forms are like LAMBDA's, except that the arguments
- of an NLAMBDA are not evaluated before it is applied,
- whereas the arguments of a LAMBDA are always evaluated
- before function application.
-
-
-
-
-
-
- 3.5 LEXPR's
-
-
- LEXPR's are an archaic programming technique which were
- dropped from the Common LISP standard, but which I will
- probably implement at some point in the future for backwards
- compatibility.
-
-
-
-
-
-
- 3.6 MACRO's
-
-
- Macros are an idea which originated outside of LISP, and
- which found its way into the language. A macro basically
- manipulates its arguments, and produces a new expression,
- which is called the macro expansion. This new expression is
- then evaluated, and the result is returned as the result of
- the macro. For example, suppose we had defined mactest as:
-
-
- (def mactest (macro (carpart cdrpart)
- (list 'cons carpart cdrpart)))
-
- Then we could type:
-
- /USR/LOGIN->(mactest 1 2)
- (1 . 2)
-
-
-
-
-
- - 35 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- The first time that the macro is evaluated, it is evaluated as
- if it were an NLAMBDA; that is, its arguments are not evaluated.
- When the result of this first evaluation is itself evaluated,
- it is evaluated normally. For example, in the above example,
- the result of the first evaluation is
-
- (list 'cons '1 '2)
-
- Since LIST evaluates its arguments, the expression evaluates to
-
- (1 . 2)
-
-
- 3.6.1 Displacing Macros
-
- So far, I have assumed that macros are expanded each time
- that they are used. However, this approach is very
- expensive in terms of speed degradation, and so various LISP
- interpreter implementors have devised ways of insuring that
- macros are only expanded once. Some LISP interpreters
- expand macros when functions are defined. PDLISP provides
- a facility whereby macros can be expanded on only the first
- occaision that they are used, and the s-expression being
- evaluated is altered to incorporate the expanded
- sub-expression. The original contents of the s-expression
- being evaluated are discarded (or "smashed").
-
-
-
-
- 3.6.2 Backquoting
-
- A useful construct when writing MACRO's is the backquoting
- system. When an s-expression is read into the system which
- is preceeded by a backquote ("`"), it is quoted. However,
- if it is a list, then every element of the list which is
- preceeded by a comma is not quoted. For example, consider
- the following dialog:
-
-
- /USR/LOGIN->`(take out the trash)
- (TAKE OUT THE TRASH)
- /USR/LOGIN->(setq trash 'junk) ;give TRASH a value.
- JUNK
- /USR/LOGIN->`(take out the ,trash) ;un-quote TRASH
- (TAKE OUT THE JUNK)
-
- Backquote also does something interesting with symbols which
- are preceeded by a comma followed by an at-sign, ",@". This
-
-
-
- - 36 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- sequence unquotes the expression which follows, just as the
- comma does, except that the resulting value must be a list.
- The elements of this list are then spliced into the list
- which was preceeded by the backquote. For example:
-
-
- /USR/LOGIN->`(by the light of the moon)
- (BY THE LIGHT OF THE MOON)
- /USR/LOGIN->(setq moon '(silvery globe))
- (SILVERY GLOBE)
- /USR/LOGIN->`(by the light of the ,@moon)
- (BY THE LIGHT OF THE SILVERY GLOBE)
-
- In the previous example of MACTEST, we could have defined
- MACTEST as
-
-
- (def mactest (macro (carpart cdrpart)
- `(cons ,carpart ,cdrpart)))
-
- The functions defining the behavior of backquote, comma, and
- comma-at are in the file bakquote.l, which is on the
- distribution disk.
-
-
-
-
- 3.6.3 The Smash Hook
-
- PDLISP provides a facility for controlling macro expansion
- called the smash hook. The actual mechanics of setting this
- hook are covered in the chapter on the STATUS function.
-
- On boot up, the macro smash flag is set to T. This is the
- ordinary mode of operation, but it does introduce the
- inconvenience of not being able to look at un-expanded
- macros with a BAKTRACE or SHOWSTACK. In order to make
- debugging easier, certain functions clear the smash flag on
- entry, and restore it to its original value on exit. (The
- debugger, for example, does this.)
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 37 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
-
-
- 3.7 Optional, Rest, and Auxilliary Parameters
-
-
- Each function has in its declaration a list of parameters
- which correspond to arguments which can or must be passed to
- it when it is run. This list is variously called the lambda
- variable list, the lambda list, or the formal parameter
- list. I shall use the last term for this concept.
-
- The parameters which are actually passed to a function at
- run-time are called its arguments, or actual parameters.
- These parameters are not known at function definition time,
- since they may vary from one invocation of the function to
- the next.
-
- When a function is executed, a part of the interpreter
- called the binder associates the formal parameter list of a
- function with the actual parameters which are being fed to
- it.
-
- Optional, rest, and auxilliary parameters are an idea
- which originated with MDL, a LISP offshoot which was
- developed at M.I.T. They provide additional flexibility in
- specifying parameter lists. Optional and rest parameters
- later found their way into LISP Machine LISP, or ZETALISP,
- as described in Moon [1974], and from there into PDLISP.
-
- In general, a function in PDLISP (or Common LISP) has
- zero or more required parameters, which may be followed by
- one or more optional parameters, which may be followed by a
- rest parameter, which may in turn be followed by any number
- of auxilliary parameters. The caller must provide enough
- arguments so that all of the required parameters are bound.
- Any extra arguments are bound by the evaluator to the
- optional parameters in the function's lambda-list. If an
- optional parameter is not "covered" by an argument, then it
- is bound to NIL. If the function's lambda list contains a
- rest parameter, then it will be bound to a list of any extra
- arguments which are left over after all of the required and
- optional parameters have been bound. If there are no
- arguments left over, then the rest parameter is bound to
- NIL.
-
- Optional parameters are specified by inserting the keyword
- &OPTIONAL in the lambda-list of a function. All parameters
- which occur after the &OPTIONAL keyword are considered
-
-
-
- - 38 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- optional by the evaluator.
-
- Rest parameters are specified in a function definition by
- the use of the keyword &REST in the lambda-list of a
- function. The parameter after the &REST keyword is taken by
- the interpreter to be the rest parameter for the function.
-
- Here is an illustration of how this works. Suppose that
- we have defined a function as follows:
-
-
- (defun funny (a b &optional c d &rest e)
- (prog ()
- ((print a) ;print a
- (terpri) ;terpri terminates the current print line
- (print b) ;print b
- (terpri) ;
- (print c) ;and so on...
- (terpri)
- (print d)
- (terpri)
- (print e)
- (terpri))))
-
- Then we could engage in a terminal session as follows:
-
-
- /USR/LOGIN->(funny 1 2 3 4 5)
- 1
- 2
- 3
- 4
- (5)
- /USR/LOGIN->(funny 1 2 3)
- 1
- 2
- 3
- NIL ;C was bound to NIL
- NIL ;as was D.
- NIL ;E, the &REST parameter, was bound to NIL
-
- It is somewhat redundant to have an &OPTIONAL &REST
- parameter; all &REST parameters are optional. If no actual
- parameters are supplied to a &REST formal parameter, then
- the &REST parameter is bound to NIL.
-
-
-
-
-
-
-
-
- - 39 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
-
-
- 3.8 Initialized &OPTIONAL parameters
-
-
- &OPTIONAL parameters can be initialized to a default
- value. If the parameter is not "covered" by an argument,
- then the interpreter will set it to its default value.
-
- In order for an &OPTIONAL parameter to have a default
- value, it must be declared as a list of the form
-
-
- (NAME VALUE)
-
- where NAME is the name of the formal parameter, and VALUE is
- its default value. For example, in the following example, B
- is an initialized &OPTIONAL parameter:
-
-
- (def inittest (nlambda (a &optional (b 3))
- (progn
- (princ "a = ")
- (print a)
- (terpri)
- (princ "b = ")
- (print b)
- (terpri))))
-
- We could then invoke INITTEST as follows:
-
- /USR/LOGIN->(inittest 2)
- a = 2
- b = 3
-
-
-
-
- 3.9 Auxilliary Parameters
-
-
- Auxilliary parameters serve as "local variables" for
- functions. Auxilliary parameters are declared in a
- function's lambda-list by including the keyword &AUX, and
- then the names of the auxilliary variables. If an
- auxilliary variable is declared as a list of the form (name
- value), then the variable is initialized the value
- specified. For example, in the following function
-
-
-
- - 40 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- definition, B and C are auxilliary parameters:
-
-
- (def auxtest (nlambda (a &aux b (c 6))
- (progn
- (princ "a = ")
- (print a)
- (terpri)
- (princ "b = ")
- (print b)
- (terpri)
- (princ "c = ")
- (print c)
- (terpri))))
-
- In the above example, B is initialized to a value of NIL,
- and C is initialized to a value of 6. So (auxtest 3) would
- result in the output:
-
-
- a = 3
- b = NIL
- c = 6
-
- Several possible error conditions are checked by the
- interpreter when a function is applied. They are:
-
-
- Not enough arguments (actual parameters) to "cover"
- all of the non-&OPTIONAL formal parameters in a function's
- lambda-list will result in the error message:
-
- "***> BINDER(): too few arguments."
-
-
- Initialization of a parameter which is not an &OPTIONAL
- or &AUX parameter will produce the error message:
-
- "***> BINDER(): initialization of non-&OPTIONAL param."
-
-
- No parameter after the &REST keyword. This will produce
- the message:
-
- "***> BINDER(): missing &REST formal parameter."
-
-
-
-
-
-
-
-
- - 41 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- More than one formal parameter after a &REST keyword,
- with no &AUX parameter will produce the message:
-
- "***> BINDER(): more than 1 &REST formal param."
-
-
- Lack of a formal parameter after an &OPTIONAL keyword
- will produce the message:
-
- "***> BINDER(): missing &OPTIONAL formal param."
-
-
- Missing parameters after the &AUX keyword. This will
- result in the message:
-
- "***> BINDER(): missing &AUX parameter(s)"
-
-
- The &AUX keyword must be the last keyword in the formal
- parameter list. Having a keyword (such as &OPTIONAL) in the
- parameter list after &AUX will trigger the message:
-
- "***> SETATOM(): formal parameter is not a symbol."
-
-
-
-
-
-
- 3.10 PDLISP Function Descriptions
-
-
- Throughout the rest of this manual, I will use a specific
- format for function descriptions. Each description is begun
- with a line in the following format:
-
-
- FN-NAME FN-TYPE FORMAL PARAMETER LIST
-
- where,
-
- FN-NAME is the name of the function,
-
- FN-TYPE describes the way that the function handles
- its parameters. This is also called the discipline
- of the function. The possible values for FN-TYPE are:
-
- CSUBR - the symbol is bound as a C subroutine, which
- means that it is a primitive subroutine in
-
-
-
- - 42 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- the kernel of the interpreter (which is
- written in C) which evaluates its parameters.
-
- CNSUBR - the symbol is bound as a C subroutine which
- does not evaluate its parameters. This
- discipline is used to describe many
- so-called special forms which may
- evaluate some or all of their arguments,
- but in a non-standard order.
-
- LAMBDA - the symbol is bound as a LAMBDA function,
- which means that it is interpreted and
- evaluates its parameters.
-
- NLAMBDA - the symbol is bound as an NLAMBDA function,
- which means that it is interpreted and does
- not evaluate its parameters.
-
- SUBR - the symbol is bound as a compiled LISP
- function which evaluates its parameters.
-
- NSUBR - the symbol is bound as a compiled LISP
- function which does not evaluate its
- parameters.
-
- MACRO - the symbol is bound as a macro, which is
- explained in the text.
-
- built-in - the symbol corresponds to a key-word in
- the language, and resides in an invisible
- "super-directory" which is not directly
- accessible to the user. The reason why
- this directory exists is so that certain
- symbols which are critical to the operation
- of the system (such as T and NIL) cannot
- be bashed. The actual way that the function
- handles arguments varies; see the individual
- function description.
-
- FORMAL PARAMETER LIST is a representation of the parameters
- which the function takes. Generally, these symbols are
- self-descriptive; for example, a parameter named ANATOM
- means that the corresponding actual parameter must be
- atomic, STR1 and STR2 mean that the corresponding parameters
- must be strings, etc. X, X1, X2, and so on correspond to
- arbitrary s-expressions. If the &OPTIONAL parameter is
- included, then the subsequent parameters are optional.
-
-
-
-
-
-
- - 43 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
-
-
-
- 3.11 Summary of Functions Presented So Far
-
-
- Having put forth the format of a function description, I
- have some catching up to do. Here is a listing of the
- functions which I have already discussed, as well as a few
- more which are generally useful in manipulating lists:
-
-
-
-
- APPEND CSUBR (&REST X)
-
- Non-destructive function which constructs a list composed
- of the elements of each of its arguments (which must be lists).
-
- for example:
- /USR/LOGIN->(append '(a b) '(c d) '(e) '() '(f))
- (a b c d e f)
-
- The last argument does not actually have to be a list, but
- may in fact be atomic, and it becomes the tail of the
- constructed list.
-
- for example:
- /USR/LOGIN->(append '(a b) '4)
- (a b . 4)
-
- See also NCONC, which is similar except that it alters all
- of its arguments except the last one.
-
-
- ATOM CSUBR (ANATOM)
-
- Returns T if its argument is atomic, otherwise returns NIL.
- (ATOM 'NIL) and (ATOM '()) both return T. Recall that
- something is an atom if it is a symbol, number, or string.
- See SYMBOLP.
-
- CAR CSUBR (X)
-
- Returns the car half of the cell X. X must not be atomic, or
- an error results. (CAR '()) ==> NIL.
-
-
-
-
-
-
- - 44 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- CDR CSUBR (X)
-
- Returns the cdr half of the cell X. X must not be atomic, or
- an error results. (CDR '()) ==> NIL.
-
-
- CONS CSUBR (X1 X2)
-
- List constructor function. (CONS X1 X2) produces a cell which
- is a dotted pair, with the car part of the cell being set
- equal to X1, and the cdr part of the cell equal to X2.
-
-
- EQ CSUBR (X1 X2)
-
- Returns T if and only if X1 and X2 are the same object or
- structure in s-expression space. Otherwise, returns NIL.
- EQ can be used to compare symbols, which are stored uniquely
- in the symbol table, but numbers and strings will not
- compare, since they are not. For example,
- (eq 'b 'b) ==> T, but (eq '(a b) '(a b)) ==> NIL.
-
-
- EQL CSUBR (X1 X2)
-
- Returns T if and only if X1 and X2 are EQ to each other
- or if they are both numbers of the same type (integer or
- float) with the same value. Since character objects are
- actually stored as symbols in PDLISP, two character
- objects are EQL if they have the same name. (See the
- chapter on directory support.) EQL does not do anything
- intelligent about comparing strings; see the descriptions
- of STREQ and STRCMP. For example,
- (eql 'a 'a) ==> T
- (eql '(a b) '(a b)) ==> NIL
- (eql 4 4) ==> T
- (eql 4 4.0) ==> NIL
-
-
- EQUAL CSUBR (X1 X2)
-
- Returns T if and only if X1 and X2 are equivalent structures.
- That is, all symbols referenced by X1 and X2 must be the same,
- but everything else must merely be isomorphic. For example,
- (equal 'a 'a) ==> T
- (equal '(a b) '(a b)) ==> T, but (eq '(a b) '(a b)) ==> NIL.
- (equal 4 4) ==> T, but (eq 4 4) ==> NIL.
-
-
-
-
-
- - 45 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- LIST CSUBR (&rest X)
-
- Constructs a list which is composed of the values of its
- arguments. For example, if A were previously defined as 4,
- then (LIST A 'B) would evaluate to (4 B).
-
-
- NUMBERP CSUBR (X)
-
- Returns T if X is an integer or a float; otherwise, returns NIL.
-
-
- QUOTE CNSUBR (X)
-
- (QUOTE X) evaluates to X. QUOTE is used to prevent evaluation
- of a form. Because QUOTE is so useful, the reader has been
- designed to translate any form preceded be a single quote
- mark (') into a QUOTE form. For example,
- ;
- ;the following expression really means (SETQ APPLE (QUOTE ORANGE))
- ;
- /USR/LOGIN->(SETQ APPLE 'ORANGE)
- ORANGE ;APPLE is set to this value
- ;
- ; omitting the quote mark causes an error, as in the following:
- ;
- /USR/LOGIN->(SETQ APPLE ORANGE) ;without the quote mark.
- ***> EVAL: variable ORANGE is unbound
- ;
- ; the evaluator tried to look up the value of ORANGE.
- ;
-
- ZEROP CSUBR (X)
-
- Returns T if X is an integer or a float equal to zero;
- otherwise returns a value of NIL. This function will not
- return reliable results on floats, since they are rarely
- exactly equal to anything.
-
-
- The following functions access or set the value and
- function definition cells of symbols:
-
- DEF NLAMBDA (X Y)
-
- Sets the function definition cell of X to Y. X must be
- a symbol, or an error results. Neither argument is evaluated.
-
-
-
-
-
- - 46 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
- GETD CSUBR (ASYMBOL)
-
- Gets the contents of the function definition cell of ASYMBOL.
-
-
- PUTD CSUBR (ASYMBOL DEFINITION)
-
- Sets the function definition cell of ASYMBOL to DEFINITION.
- Both arguments are evaluated.
-
-
- SET CSUBR (ASYMBOL VALUE)
-
- Sets the value cell of a symbol (ASYMBOL) to VALUE. Unlike
- lambda-binding, this operation is destructive, in that the
- previous binding of ASYMBOL is not saved somewhere and
- restored later. The current function cell value of ASYMBOL,
- if it has one, is not altered.
-
-
- SETQ CNSUBR (ASYMBOL VALUE)
-
- Same as SET, except that this function quotes (does not
- evaluate) its first argument.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 47 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 48 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 49 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 50 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 51 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 52 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 53 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual User-Defined Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 54 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
-
-
-
-
-
-
- Chapter 4
-
- Program Development in PDLISP
-
-
-
-
-
-
-
-
- 4.1 What's a Program?
-
-
- In PDLISP, a program is considered to be a sequence of
- function definitions, which are usually available in the
- form of text-files. From PDLISP, one can invoke
- conventional text editors using the shell escape. The shell
- escape feature of PDLISP allows access to other programs
- residing on the host operating system (O/S), and is invoked
- by typing an exclamation point (!) after the PDLISP prompt,
- followed by a command which will be sent to the host O/S.
- For example, if we were running under MS-DOS (PC-DOS), we
- could invoke the excellent editor MINCE, which is published
- by a company called Mark of the Unicorn as follows:
-
-
- /USR/LOGIN->!mince foo.bar
-
- (and MINCE would start executing).
-
- Upon completion of the MINCE session, instead of returning
- to the O/S, control transfers back to PDLISP. The PDLISP
- environment should be unchanged from the point where it was
- exited. That is, all variables, functions, and their
- bindings (values) should be intact. At that point, the
- programmer should read in the file which he has just edited
- using one of the functions LOAD or LOADV.
-
- More information about the shell escape feature and
- related functions is contained in the chapter of this manual
- entitled "Interfacing to the Operating System."
-
- For example, suppose that a file called foo.l exists on
-
-
-
- - 55 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
- disk. Then, the file can be read in as follows:
-
-
- /USR/LOGIN->(load "foo.l")
- T
-
- All of the load functions are functions of 1 argument,
- which must be a string. These functions evaluate their
- argument, but since strings evaluate to themselves (i.e.,
- they are automatically quoted), it is not necessary to QUOTE
- the argument. These functions all evaluate each expression
- in a file as they read it from beginning to end. These
- functions return as their values T if they were successful,
- and return NIL if they do not succeed. LOADV, besides
- returning their values, prints out on the screen the value
- of each s-expression as it is read. The 'V' in LOADV stands
- for the word 'verbose'.
-
- As an example of the usage of the load functions, consider
- the following dialog whereby the user is loading in the file
- RUDOLF.L, which is on the distribution disk.
-
-
- /USR/LOGIN->(load "rudolf.l")
- T ;this is the value returned by LOAD.
- /USR/LOGIN->(loadv "rudolf.l")
- RED ;rudolf has a red nose,
- GREEN ;a green scarf,
- BLACK ;black hooves,
- BROWN ;brown fur,
- BLUE ;blue eyes,
- BIG ;big antlers,
- FAT ;and a fat tummy.
- T ;T here indicates that LOAD was successful.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 56 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
-
-
-
-
- 4.2 Saving and Restoring PDLISP Sessions
-
-
- After many files have been 'read in' to the PDLISP
- system, the user may not wish to have to repeat the
- process. The SAVE and RESTORE functions enable the user to
- store the current state of the machine on disk, and to
- retrieve it in a later session.
-
- For example, we could type the following to save a virtual
- image:
-
-
- /USR/LOGIN->(save "foo.img")
- T
-
- The T returned by eval indicates that the current state of
- the machine (called the "virtual image" in PDLISP) has been
- saved on disk with the file name of foo.img. The double
- quote marks around the file name are necessary, and they
- make the file name a string in PDLISP. The suffix, ".img",
- is a PDLISP convention which stands for the word "image".
- In the remainder of this document, files which have been
- saved to disk using the SAVE function will be referred to as
- "image files."
-
- If later we wished to resume the computation at the point
- at which it was saved, the sequence below would work:
-
-
- /USR/LOGIN->(restore "foo.img")
- T
-
- By the way, we could have used as the file name any name
- which is legal for the host operating system. For PC-DOS
- (MS-DOS), we could have written "b:foo.img", or
- "a:\syslib\unhacks\foo.img". For examples of legal file
- names, consult the instruction manual for your operating
- system.
-
-
-
-
-
-
-
-
-
-
- - 57 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
-
-
-
-
- 4.3 Summary of Virtual Image Commands
-
-
-
- RESTORE CSUBR (STR)
-
- Restores a virtual image from disk. STR must be the name of
- a file which contains a virtual image which had previously
- been saved.
-
-
-
-
- SAVE CSUBR (STR)
-
- Saves the current virtual image to a disk file, which is
- specifed by STR.
-
-
-
-
- 4.4 Booting Up PDLISP
-
-
- The following section is correct when PDLISP is running on
- UNIX; however, when running on MS-DOS a slightly different
- procedure is used. Consult the appendix on MS-DOS for more
- information.
-
- PDLISP can be booted (started) in one of two ways.
- PDLISP can be brought up with the command line
-
-
- PDLISP
-
- When PDLISP is brought up this way, it immediately searches
- the current directory of the disk for the file named
- "unxinit.l." If unxinit.l is found, then it is read in.
- Otherwise, an error message is output.
-
- PDLISP can also be brought up by typing the command line:
-
-
- PDLISP <filename>
-
- where <filename> is the name of some image file. In this
-
-
-
- - 58 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
- case, PDLISP does not search for unxinit.l. Instead, it
- restores the file named. The virtual image is then restored
- to the exact state that it was in when the image file was
- created. This is the normal way that a programmer insures
- continuity of the virtual image from one session to the
- next.
-
- An image file, "unx.img", may be present on the
- distribution disk. This image file was created by saving
- the virtual image after dirlib.l and other utility libraries
- had been loaded. This image file can be restored by typing:
-
-
- PDLISP unx.img
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 59 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 60 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Program Development in PDLISP
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 61 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
-
-
-
-
-
- Chapter 5
-
- List Processing Functions
-
-
-
- This chapter contains descriptions of miscellaneous
- functions which are useful in manipulation of s-expressions
- which are lists.
-
-
- ADD-TO-LIST LAMBDA (E L)
-
- Adds element E to the list L if it is not already a member of
- L. The new list is returned. The original list is not
- altered. For example,
-
- /USR/LOGIN->(add-to-list 'd '(a b c))
- (D A B C) ;D is CONS'ed onto the front of the list.
- /USR/LOGIN->(add-to-list 'd '(a b c d))
- (A B C D) ;nothing happens in this case.
-
-
- CONSP CSUBR (X)
-
- Returns T if X is a cons cell (i.e., not atomic).
- Otherwise, returns NIL. (CONSP '()) evaluates to NIL.
- For example,
- (consp 4.5) ==> NIL
- (consp 6) ==> NIL
- (consp '(a b)) ==> T
- (consp 'c) ==> NIL
-
-
- COPY-LIST CSUBR (X)
- Returns a list which is EQUAL to X, but not EQ to it.
- Only the top-most level of X is copied; everything
- below the top-most level is composed of the elements
- of X. This is accomplished by copying in the CDR
- direction, but not in the CAR direction. For example,
-
-
-
-
-
-
-
- - 62 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
- /USR/LOGIN->(setq a '(x (y z))) ;set A to something.
- (X (Y Z)) ;here's the result.
- /USR/LOGIN->(setq b (copy-list a)) ;make B a copy of A.
- (X (Y Z)) ;looks the same.
- /USR/LOGIN->(equal a b) ;A is EQUAL to B
- T
- /USR/LOGIN->(eq a b) ;but not EQ to it.
- NIL
- /USR/LOGIN->(rplacd (cdr b) 'w) ;let's bend some links.
- (W)
- /USR/LOGIN->a ;nothing happened to A,
- (X (Y Z))
- /USR/LOGIN->b ;but B has changed.
- (X W)
-
- The RPLACD function which was used in the above example
- is described in the next section.
-
-
- COPY-TREE CSUBR (X)
- This function is similar to COPY-LIST, which is described
- above, but all cons cells in X are copied, and not just those
- at the top-most level of the list.
-
-
- CXXR, CXXXR CSUBR (X)
-
- Each member of this family of functions are composition
- functions of CAR and CDR. Each letter between 'C' and 'R' can
- be an 'A' or a 'D'. For example, (CADR X) would be equivalent
- to (CAR (CDR X)).
-
-
- DELETE CSUBR (X L)
-
- Deletes all elements of L which are EQL to X. For example,
- (delete '4 '(a b 4 c)) ==> (a b c)
-
-
- FIRSTN LAMBDA (N X)
-
- Returns a list consisting of the first N elements of X.
- If N is greater than the length of X, then X is returned.
- If N is less than or equal to 0, then NIL is returned.
- Source is in misc.l
-
-
-
-
-
-
-
- - 63 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
- LAST CSUBR (X)
-
- Returns the last cons cell of a list. Note - this is NOT
- the same as the last element of a list. For example,
- (last '(a b c d e)) ==> (e), and
- (last '(a b (c . d))) => (c . d).
-
-
- LENGTH CSUBR (X)
-
- Returns the length of a list. If X is not a list, then returns 0.
- (length '(a b c)) ==> 3, (length '(a b (c d) e)) ==> 4
-
-
- LISTP CSUBR (X)
-
- Returns T if X is a cons (i.e., not atomic), or EQL to the
- empty list (which can be written as "()" or as "NIL").
- LISTP does not actually analyze X to ascertain whether
- or not it is a legal list; for example,
- (LISTP '(A B)) ==> T
- (LISTP '(A . B)) ==> T, even though (a . b) is not actually
- a list.
-
-
- MEMBER CSUBR (ITEM SET)
-
- Returns the largest tail of SET which has ITEM as a member.
- Only the top-most level of SET is examined. For example,
- (member 'b '(a b c d e)) ==> (b c d e)
-
-
- NTHCDR LAMBDA (N X)
-
- Returns the result of CDR'ing down X N times.
- For example,
-
- (nthcdr 0 '(a b c)) ==> (a b c)
- (nthcdr 1 '(a b c)) ==> (b c)
- (nthcdr 6 '(a b c)) ==> ()
- (nthcdr -1 '(a b c)) ==> (a b c)
-
- Source for this function is in misc.l.
-
-
-
-
-
-
-
-
-
- - 64 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
- NULL CSUBR (X)
-
- Returns T if X is EQ to NIL; otherwise returns NIL.
- (null 'a) ==> NIL
- (null '()) ==> T
- (null 'NIL) ==> T
- (null 'T) ==> NIL
-
-
- REVERSE CSUBR (X)
-
- Returns a new list which is the reverse of its argument.
- The original list is not altered.
-
- (reverse '(a b c d e)) ==> (e d c b a)
- (reverse '(a (b . c)) ==> ((b . c) a)
- (reverse '()) ==> NIL
-
-
-
-
- 5.1 Miscellaneous Predicates
-
-
-
- BOUNDP CSUBR (ASYMBOL)
-
- Returns T if its argument (which must be a symbol) is bound
- as something, otherwise returns NIL.
-
-
- TYPE LAMBDA (X)
-
- Returns the functional type of X, which must be a symbol.
- If X is not a symbol, then an error is generated.
-
-
- COMPILED-FUNCTION-P LAMBDA (X)
-
- Returns T if X is a compiled function (i.e., a CSUBR,
- CNSUBR, SUBR, or NSUBR); otherwise returns NIL.
- X must be a symbol, or an error is generated.
-
-
- CNSUBRP LAMBDA (X)
-
- Returns T if X is a CNSUBR; otherwise returns NIL.
-
-
-
-
-
- - 65 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
- CSUBRP LAMBDA (X)
-
- Returns T if X is a CSUBR; otherwise returns NIL.
-
-
- SUBRP LAMBDA (X)
-
- Returns T if X is a SUBR; otherwise returns NIL.
-
-
- NSUBRP LAMBDA (X)
-
- Returns T if X is an NSUBR; otherwise returns NIL.
-
-
- DIRP CSUBR (X)
-
- Returns T if X is a directory; otherwise returns NIL.
-
-
- SYMBOLP CSUBR (X)
-
- Returns T if X is a symbol (i.e., an atom on the object
- list), otherwise returns NIL.
- (symbolp 'a) ==> T
- (symbolp '4) ==> NIL
- (symbolp '(a . b)) ==> NIL
- (symbolp 't) ==> T
-
-
- VARP CSUBR (X)
-
- Returns T if X has been bound as a variable (using SET or
- SETQ). Otherwise returns NIL.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 66 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
-
-
-
- 5.2 Surgical Functions
-
-
- Surgical functions, also called destructive functions, are
- functions which permanently alter one or more of their
- arguments. In the jargon of functional programming, they
- have side effects.
-
-
- NCONC CSUBR (&rest LISTS)
-
- This function alters the CDR cell of the last cons cell
- of each of its arguments (except the last one) to point
- to the next argument. The net effect of this function
- is the same as if APPEND had been used, except that
- the arguments are themselves altered, whereas APPEND
- creates an entirely new list and leaves the original
- ones intact. For example,
-
- /USR/LOGIN->(setq a '(q r s))
- (q r s)
- /USR/LOGIN->(setq b '(t u v))
- (t u v)
- /USR/LOGIN->(nconc a b) ;apply nconc
- (q r s t u v)
- /USR/LOGIN->a ;a is permanently altered
- (q r s t u v)
- /USR/LOGIN->b ;but b is the same as before
- (t u v)
-
-
- RPLACA CSUBR (X Y)
-
- Stands for RePLAce CAr; the car field of X is replaced by Y.
- The previous contents of X's car field is discarded. X must
- be a non-atomic node, or an error will result. This function,
- like all "surgical functions", is rather dangerous, and
- should be avoided if at all possible.
-
-
- RPLACD CSUBR (X Y)
-
- Same as RPLACA, except that the cdr field is replaced.
-
-
-
-
-
-
- - 67 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
-
-
-
- 5.3 TCONC Structures
-
-
-
-
- A tconc structure is a type of s-expression with
- pointers to both the head and tail of a list. A
- tconc cell is just a cons cell whose car points
- to the head of some list, and whose cdr points to
- the tail (last cons) of the same list. The reason
- why tconc cells were invented is that they
- facilitate appending something to the end of a list.
-
- Source for all of these functions is in misc.l.
-
-
- MAKE-TCONC NLAMBDA ()
- Creates a new tconc structure and returns it. All such
- structures are initially EQUAL to (NIL . NIL).
-
-
- REMOVE-FIRST LAMBDA (X)
- Removes the first element from the tconc cell X, and
- returns it.
-
-
- TCONC LAMBDA (X Y)
- Appends an element, Y, to the front of a tconc structure, X.
-
-
- LCONC LAMBDA (X Y)
- Appends an element, Y, to the end of a tconc structure, X.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 68 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 69 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual List Processing Functions
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 70 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
-
-
- Chapter 6
-
- PDLISP Directory Structure
-
-
-
- Suppose we assigned a variable a value, and subsequently
- read in a file (using one of the LOAD instructions) which
- had its own variable of the same name. The original value
- of our variable would get "clobbered", because the part of
- the PDLISP interpreter called the reader always interprets
- two variables with the same name to be the same symbol. If
- a programmer were to read in a file which was written by
- another person, there would obviously be numerous name
- conflicts which could be difficult to resolve. For this
- reason, as well as for the improved modularity which
- results, a tree-structured directory structure has been
- provided in PDLISP. This directory structure was inspired
- by the UNIX(tm) operating system, which was invented at ATT
- Bell Laboratories in New Jersey.
-
- Directories impose a structure on the data stored by the
- PDLISP system as a whole, which is referred to as the
- object list. The object list contains all symbols which
- have been defined by the user or the system.
-
- Directories are actually just a particular type of symbol,
- much as variables are. PDLISP sets up some directories for
- its own use at system initialization time. The most
- important of these is the "root" directory. All symbols in
- the system can be found by tracing a path through a sequence
- of directories, starting with the root directory, until the
- desired symbol is reached.
-
- Symbols are named by sequences of alphanumeric (and some
- other) characters starting with letters. When a name of a
- symbol is specified to PDLISP, it may be in the form of a
- path-name. . A path-name is a sequence of directory names
- which are separated by slashes ("/") which end in an symbol
- name. The symbol named at the end of the path-name may
- itself be a directory. If the path-name begins with a
- slash, then PDLISP begins its search in the root
- directory. The name "/" refers to the root directory
- itself. Thus, the name "/SYS/CMD" refers to the
-
-
-
- - 71 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- subdirectory "CMD" which is located in the directory "SYS",
- which is in turn located in the root directory.
-
- As an abbreviation, a path name which does not begin with
- a slash causes PDLISP to begin its search in the user's
- current directory. Thus, the path-name "BLUE/GREEN" would
- cause PDLISP to search the current directory for an symbol
- named "BLUE" (which must itself be a directory), and then in
- that directory for an symbol named "GREEN".
-
- The same symbol name may occur in more than one directory,
- but two symbols are the same if and only if they have
- identical path-names. Two distinct symbols with the same
- name cannot exist in the same directory. For example, the
- symbols /SYS/CMD/BLUE and /USR/LOGIN/BLUE could both coexist
- in the same directory tree, but they reside in different
- directories. Their path-names differ, but not the last
- segment of their path-names, which are their symbol names.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 72 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
- 6.1 Initial PDLISP Directory Configuration
-
-
- At system initialization time, the following object list is
- set up:
-
-
- / (root symbol)
- |
- +-------------+-------------+
- | |
- SYS (system directory) USR (user directory)
- | |
- +--------+--------+ |
- | | |
- CMD CONST LOGIN
- | |
- +----+----+ +-----+-----+
- | | | | | |
- LED LCOMP LASM (various global symbols)
-
- The root directory, "/", is the top (bottom?) of the entire
- object list structure. From root, the tree is divided into
- 2 main sub-directories, /SYS and /USR. /SYS is where PDLISP
- utilities and constants reside. For example, LED, the
- PDLISP structure editor, LCOMP, the PDLISP compiler, as
- well as other system utilities will be loaded into /SYS/CMD
- (after they have been written, of course). The user is
- initially logged in at the directory /USR/LOGIN. His
- application programs are assumed to be built from his login
- directory, although this is not necessary. First of all,
- the most important symbol in the entire object list is the
- root symbol, which has a pathname of "/". For example, if we
- wanted to find out the value of the root, we could type in
- the following:
-
-
- /USR/LOGIN->/
- (sys usr)
-
- The value of root, as with all directories, is just a list
- of the symbols which are on it. If we wished to refer to
- the sys subdirectory of the root directory, we would write
- "/SYS". /SYS/CMD would refer to the "CMD" directory, which
- is located in the "sys" directory, which, in turn, is
- located in the root ("/") directory.
-
-
-
- - 73 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
- PDLISP provides a facility for customizing the prompt
- which is printed in the top-level loop of the interpreter.
- In the file dirlib.l, the prompt is set up so that the
- interpreter prints out the directory on the top-level prompt
- line. For example, if the user were in /SYS/CMD, then the
- interpreter would print out
-
-
- /SYS/CMD->
-
- as the top level prompt. For more information about setting
- your own prompt function, consult the chapter on hook
- functions.
-
-
-
-
- 6.2 Creating Directories
-
-
- In PDLISP, directories are a type of symbol. Directories
- are created by the MD and MDQ functions. MD stands for
- "make directory", and it creates a new one. MDQ is
- identical, except that it quotes its argument. For example,
- the expression (MDQ RUDOLF) would create a new directory
- called rudolf.
-
- The functions CD and CDQ change the current directory. CD
- stands for "change directory". For example, the expression
- (CD 'RUDOLF) would change the current directory to be the
- directory rudolf. In this example, rudolf must be a
- directory symbol in the current directory, because we did
- not specify a complete pathname. That is, directory names
- which do not begin with / (which stands for the root
- directory), are assumed by the reader to be sub-directories
- of the current directory. This saves a lot of typing,
- because in most cases, only the 'tail' of the directory name
- has to be typed.
-
- In the following dialogue, a subdirectory of the current
- directory is created, and it is made the current directory:
-
-
-
-
-
-
-
-
-
-
-
- - 74 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
- /USR/LOGIN->(mdq rudolf) ;make directory RUDOLF
- RUDOLF ;last segment of the path-name
- /USR/LOGIN->(cdq rudolf) ;go to it
- RUDOLF ;value returned by CDQ
- /USR/LOGIN/RUDOLF-> ;PDLISP prompt reflects
- ;the new current directory.
-
- At the conclusion of the above dialogue, the PDLISP prompt
- line contains '/USR/LOGIN/RUDOLF', whereas formerly it
- contained the string '/USR/LOGIN'. This change will remain
- in effect until the current directory is changed to be
- something else.
-
- At this point, some terminology is in order. When a
- directory is created, it is called a 'child' directory, or a
- 'sub-directory.' The directory immediately above it (and
- normally there can only be one such directory) is called its
- parent.
-
- The same terminology holds for normal symbols. Each
- symbol resides in exactly one directory, and that directory
- is called its parent.
-
- The commands MCD and MCDQ are similar to the above
- functions, but they combine the MD and MDQ functions with
- the CD and CDQ functions. MCD stands for "make and change
- current directory". For example, we could compress the
- above dialogue into the following:
-
-
- /USR/LOGIN->(mcdq rudolf) ;make rudolf
- RUDOLF ;value returned from MCDQ
- /USR/LOGIN/RUDOLF-> ;PDLISP prompt is changed, too.
-
-
-
-
- 6.3 The $ and $$ symbols
-
-
- Quite often, the PDLISP programmer will want to refer to
- the current directory and the parent of the current
- directory. Some special machinery has been provided for
- this purpose. Whenever PDLISP creates a directory, it
- automatically installs two special symbols in that
- directory. These symbols are named "$" and "$$", and they
- correspond to the "." and ".." files under UNIX and MS-DOS
- (or PC-DOS). The $ symbol is bound to its parent directory,
-
-
-
- - 75 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- and the $$ symbol is bound to the parent of its parent.
-
- For example, the expression (cd $$) changes the current
- directory to be the parent of the current directory. Note
- that we used the unquoted form of the CD function here - we
- want to go to the value of $$, and so we want the evaluator
- to evaluate $$.
-
- A useful side-effect of the way that PDLISP stores
- directory information is that the value of a directory is a
- list of the symbols which are in that directory. For
- example, the value of the root directory upon boot-up is the
- list (SYS USR ). Since we can get the value of any variable
- simply by evaluating it, we could type:
-
-
- /USR/LOGIN->/ ;Get the value of the root directory.
- (SYS USR ) ;The value is always a list (or NIL).
- /USR/LOGIN->$ ;We can also get the name of the
- LOGIN ; current directory by evaluating $
- /USR/LOGIN->(eval $)
- ($ $$ RUDOLF TEST) ;RUDOLF and TEST are its children
- /USR/LOGIN->$$ ;Same for parent of current directory
- USR ;value of parent
- /USR/LOGIN->(eval $$) ;evaluating parent of current directory
- ($ $$ LOGIN) ;gives names of symbols in it.
-
-
-
-
- 6.4 PARENT and PARENTQ functions
-
-
- The function PARENT returns the parent directory of its
- argument. PARENTQ is an equivalent function which quotes
- its argument. The expression (PARENTQ $) would evaluate to
- the parent of the current directory. For example:
-
-
- /USR/LOGIN->(parentq $) ;get parent of current directory.
- USR ;value returned.
- /USR/LOGIN->$$ ;same thing.
- USR ;same value returned.
-
- The actual results which you obtain may be different,
- depending upon where you are on the directory tree and what
- sub-directories you have created.
-
-
-
-
-
-
- - 76 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
- 6.5 The Reader Search Path
-
-
- The reader is the part of the interpreter which reads
- s-expressions in from the console or a file. Basically,
- when the reader reads an symbol name, it must determine
- whether the name refers to a new object or to one which
- already exists in the object list. If the object already
- exists, then the reader returns a pointer to that object.
- If the object does not exist, then the reader constructs a
- new object (in the current directory) and returns a pointer
- to it.
-
- In determining if an object exists in the object list, the
- reader selectively searches the object list along what is
- called the reader search path. This search path is just a
- list of directories to be searched by the reader. The
- search always starts first in the current directory. If the
- symbol cannot be found in that directory, then the search
- continues with the first directory in the reader search path
- and proceeds down to the end of the list. If the symbol
- still cannot be found, then it is built in the current
- directory.
-
- This search path is user-configurable using the function
- STATUS. for example,
-
-
- /USR/LOGIN-> (STATUS reader_search_path '(/usr/lib /sys/cmd)))
-
- would set up the reader search path so that the reader first
- looks in the current directory (whatever that may be), then
- the directory /USR/LIB, and finally the directory /SYS/CMD.
- If the symbol name cannot be found in any of those
- directories, then a new symbol is created in the current
- directory. (STATUS reader_search_path) returns the current
- value of the reader search path.
-
- More elaborate functions for accessing and manipulating
- the reader search path are described in the function summary
- at the end of this chapter. In particular, see ADD-TO-PATH,
- GETPATH, POPPATH, PUSHPATH, REMOVE-FROM-PATH, and SETPATH.
-
-
-
-
-
-
-
- - 77 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
- 6.6 Directory Prefixes
-
-
- PDLISP accepts certain abreviations for certain
- directories so as to minimize typing.
-
-
-
-
- 6.6.1 The Current Directory Prefix
-
- Preceeding a symbol's name by the underscore (_) will force
- it to be in the present directory. This can be particularly
- useful if a long reader search path has been specified.
-
- STATUS also allows the user to examine and modify the the
- behavior of the system with regard to the printing of symbol
- names. Invoking (STATUS DIRECTORY_PREFIX T) causes PDLISP
- to enter a mode whereby it will print out the names of all
- symbols which are in the current directory with an
- underscore prefix. If (STATUS DIRECTORY_PREFIX NIL) is
- invoked, then no symbol names will be printed with an
- underscore prefix.
-
- Throughout the rest of this chapter, the underscore prefix
- will be printed as if (STATUS DIRECTORY_PREFIX T) had been
- invoked.
-
-
- 6.6.2 The Directory Suffix
-
- Whenever PDLISP prints out the name of an symbol which is
- a directory, it appends a slash (/) at the end of the name.
- This is in order to facilitate identification of directory
- structure without having to invoke a special utility
- function. For example, if we had a directory symbol named
- "CMD", then the system would output its name as "CMD/".
-
-
-
-
-
-
-
-
-
-
-
-
- - 78 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
- 6.7 The DIR Function
-
-
- In order to view the contents of the current directory,
- the DIR function has been provided in the the file
- dirlib.l. For example, if the current directory were empty,
- then the following dialog would occur:
-
-
- /USR/LOGIN->(dir)
- (_$ _$$) ;symbols in current directory
-
-
-
-
- 6.8 The LQ function
-
-
- LQ is similar to DIR, except that its display is more
- elaborate. LQ takes one optional argument, which must be a
- directory symbol, and displays a line of information for
- each symbol in that directory. If the directory argument is
- not present, then the current directory is assumed as a
- default. For example, in the following dialog, we create a
- new directory called /USR/LOGIN/STUFF, and load some symbols
- into in from a file called "examples.l", which is on the
- distribution disk.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 79 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
- /USR/LOGIN->(mcdq stuff)
- T
- /USR/LOGIN/STUFF->(lq stuff) ;let's look at the new directory.
- _$ -v --- ;_$ is setq'd to this directory
- _$$ -v --- ;_$$ is setq'd to parent directory
- T
- ;
- ;now to load some clutter
- ;
- /USR/LOGIN/STUFF->(loadv "examples.l")
- RFIB ;LOADV echoes the name of each
- IPOWER ;function as it is read.
- IFACT ;
-
- ... ;etc.
-
- T ;LOADV returns a value of T.
- /USR/LOGIN/STUFF->(lq) ;let's lq it.
- _$ -v --- ;_$ is bound as a variable
- _$$ -v --- ;... as is _$$
- _APP -v LAMBDA ;_APP is a LAMBDA - function
- _COUNT -v --- ;_COUNT is not bound as anything.
- _EXPONENT -v --- ;etc.
-
- ... ;and so on down the list.
- ;until finally LQ returns
- T ; its own value.
- /USR/LOGIN/STUFF-> ;back to standard prompt.
-
- Of course, the actual contents of any particular directory
- might be different depending upon the present configuration
- of your system. For example, if you had previously loaded
- in the file "examples.l" somewhere else in your directory
- tree, and that directory was on the reader search path for
- your system, then /USR/LOGIN/STUFF might wind up being
- empty, even if you loaded in the file a second time. This
- might happen because the reader would assume that it had
- already read in the symbols in the file, so that it would
- not construct any new symbols. The surest way to prevent a
- mistake like this from happening is to constantly look for
- the underscore prefix which the interpreter prints out
- before symbols which are in the current directory. If the
- underscore isn't there, then you can safely assume that the
- symbol is not in your current directory.
-
-
-
-
-
-
-
- - 80 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- 6.9 Global and Local Symbols
-
-
- PDLISP provides a facility whereby symbols can be made
- invisible to the system reader when the directory to which
- they belong is not the current directory. Symbols which are
- visible to the reader outside of their own directory are
- called global symbols. Symbols which are not visible
- outside of their own directory are called local symbols.
-
- As a practical example, suppose that we are currently in
- the directory /USR/LOGIN. Furthermore, assume that there
- exists in the directory /SYS/CMD a symbol called FOO, and
- that /SYS/CMD is on the reader search path (as is usually
- the case). If FOO were a local symbol, then we would be
- unable to access it, as illustrated below:
-
-
- /USR/LOGIN->foo ;get foo's value
- ***> EVAL: variable FOO is unbound.
- /USR/LOGIN->(setq foo 4) ;set foo to something
- 4 ;did we succeed ?
- ;
- ; let's look at the current directory:
- ;
- /USR/LOGIN->(lq)
- $ -v ---
- $$ -v ---
- FOO -v ---
- T
-
- Not only were we unable to get FOO's value, but we could not
- set it to a value, either. All that we accomplished was the
- creation of a new symbol, also called FOO, in the current
- directory, instead of the alteration of /SYS/CMD/FOO.
-
- None of this should be mysterious once the operation of
- the reader is understood; when the name FOO was read in,
- first the current directory (/USR/LOGIN) was scanned for a
- symbol named FOO. Since FOO did not yet exist in /USR/LOGIN,
- each of the directories along the reader search path were
- scanned. Since /SYS/CMD/FOO was not a global symbol, the
- reader did not find it, and so a new symbol named FOO was
- created in /USR/LOGIN. The full path-name of this new symbol
- is /USR/LOGIN/FOO.
-
- Now let's suppose that a global symbol named /SYS/CMD/FOO
- exists. Using LQ, we might see:
-
-
-
-
-
- - 81 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- /USR/LOGIN->(lq /sys/cmd)
-
- (lots of symbols)
-
- ...
-
- FOO gv ---
-
- ...
-
- (many more symbols)
-
- T ;value of LQ
-
- The 'g' in the column immediately after the symbol's name
- indicates that FOO is a global symbol. We should now be
- able to access it from within /USR/LOGIN.
-
-
- /USR/LOGIN->(setq foo 4)
- 4
- /USR/LOGIN->foo ;let's get the value of foo
- 4 ;foo bound as 4
- /USR/LOGIN->(lq) ;is foo in the current directory?
- $ -v ---
- $$ -v ---
- T ;apparently not.
-
- All symbols (except directories, as noted below) are
- ordinarily local when they are created by the reader. In
- order to make a symbol global, one must use the GLOBAL
- function. Usually, this takes the form of a statement near
- the beginning of the file in which the symbol is defined.
- For example, we might write:
-
-
- (global 'foo 'bar 'baz)
-
- where FOO, BAR, and BAZ are symbols which are created when
- the file is read in by the system. It should be obvious
- that the GLOBAL function can only be used when the symbols
- being made global are in the current directory; otherwise,
- of course, the PDLISP reader will prevent us from being
- able to refer to them.
-
- As noted above, all symbols (except for directories) are
- by default local symbols when they are created by the
- reader. In order to be visible outside of the directory in
- which they are created, the GLOBAL function must be used.
- Otherwise, when a directory is created with the MD, MDQ,
-
-
-
- - 82 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- MCD, or MCDQ functions, it is by default made into a global
- symbol; directories can be made local via the LOCAL
- function.
-
-
-
-
-
-
- 6.10 RM and RMQ
-
-
- Oftentimes, a programmer will inadvertantly create a
- symbol in the current directory when he or she was
- attempting to address one in another directory. This might
- happen, for example, if the PDLISP reader could not find
- the named symbol along the reader search path. For
- occaisions such as this, the RM and RMQ functions have been
- provided. RM and RMQ have as their effect the removal of
- any symbols passed to them from the object list. For
- example, we could type:
-
-
- /USR/LOGIN->(RM '_RED '_BLUE '_YELLOW)
-
- and that would have the effect of removing the symbols RED,
- BLUE, and YELLOW from the current directory. As a
- precautionary measure, these functions are incapable of
- removing symbols which are not in the current directory.
- For example, suppose that we attempted to remove a symbol
- named GREEN from a directory other than the current one.
- This would result in an error message:
-
-
- /USR/LOGIN->(RMQ GREEN)
- ***> RM or RMQ: symbol GREEN not in current directory
- NIL
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 83 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
- 6.11 RMDIR and RMDIRQ
-
-
- For safety reasons, RM and RMQ are incapable of removing
- symbols which are directory symbols. For this purpose, the
- RMDIR and RMDIRQ functions have been provided.
- (RMDIR SOMEDIR) will remove a directory named SOMEDIR from
- the current directory. RMDIRQ is similar in function,
- except that it quotes its argument.
-
-
-
-
- 6.12 PD, PDQ, and POPD
-
-
- These functions allow a programmer to move through the
- directory hierarchy while leaving a "thread" behind
- himself. Later on, the programmer can "pop" back along the
- thread. PD and PDQ change the working directory to a new
- one, and save the current directory on a "stack." POPD pops
- the directory stack, restoring the previous entry. For
- example:
-
-
- /USR/LOGIN->(pdq /sys/cmd) ;pdq quotes its argument.
- CMD/ ;new directory returned as value.
- /SYS/CMD->(popd) ;let's pop back along the thread.
- LOGIN/ ;we're back in /USR/LOGIN.
- /USR/LOGIN-> ;prompt indicates new directory.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 84 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
-
-
-
- 6.13 Common Mistakes when Using Directories
-
-
- As with any mousetrap, directories can snap at the wrong
- time. The most common error entails the creation of symbols
- in different directories with duplicate print-names. Two
- distinct symbols cannot have identical path-names; however
- they can have identical print-names, which correspond to
- last segment of the path name. For example, suppose that we
- have two symbols, /USR/LOGIN/FOO/BAR and /USR/LOGIN/BAZ/BAR.
- The two symbols do not have the same path-names, but their
- print-names are both "bar", since ordinarily this is the
- only part of the path-name which is printed out.
-
- Now, suppose that we are currently in /USR/LOGIN/FOO, and
- that we wish to refer to /USR/LOGIN/BAZ/BAR. If, for
- example, we typed
-
-
- /USR/LOGIN/FOO->(setq bar 4)
- 4
-
- One might imagine that we had set /USR/LOGIN/FOO/BAR to 4.
- In reality, we may simply have created a new symbol,
- /USR/LOGIN/FOO/BAR, and SETQ'd it to 4. This might have
- occurred for any of several reasons.
-
-
- (1) USR/LOGIN/BAZ had not been installed on the reader's
- search path. The reader cannot refer to symbols which
- are not in the current directory or on the search path.
-
- (2) /USR/LOGIN/BAS/FOO had never been declared a global
- symbol, the GLOBAL function. Symbols which are not global
- are not visible to the reader unless they happen to reside
- in the current directory.
-
- (3) /USR/LOGIN/BAR/FOO had been created by mistake due to
- (1) or (2), above, and the user never became aware of
- its existence. Since the reader always looks first
- in the current directory, /USR/LOGIN/BAZ/FOO is
- effectively "shadowed" by /USR/LOGIN/BAR/FOO.
- The remedy in this case is to remove /USR/LOGIN/BAR/FOO
- by using the RMQ command, as follows:
-
-
-
-
-
- - 85 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
- /USR/LOGIN/BAR->(rmq foo)
- T
-
-
-
-
- 6.14 Functional Directories
-
-
- Functional directories are symbols which are simultaneously
- defined as functions and as directories. They are useful
- for "hiding" local symbols inside of functions so that the
- object list doesn't get cluttered up with junk.
-
- For example, suppose that we wish to build a utility
- called "superfoo", and that we wish to put it in /SYS/CMD/.
- We would start by creating a new directory and changing to
- it, as follows:
-
-
- /USR/LOGIN->(cdq /sys/cmd) ;move over to /sys/cmd
- CMD/
- /SYS/CMD->(mdq superfoo) ;make new directory
- SUPERFOO/
- /SYS/CMD->(cdq superfoo) ;change to it
- SUPERFOO/
- /SYS/CMD/SUPERFOO-> ;now in superfoo
-
- At this point, we can define superfoo as a function using
- the DEF$ function as follows:
-
-
- ;
- ; define $ as a lambda:
- ;
- /SYS/CMD/SUPERFOO->(def$ (lambda (x y) (+ x y)))
- SUPERFOO/
-
- If we were to examine the current directory at this point
- using LQ, we would find X and Y interned as local symbols,
- as follows:
-
-
- /SYS/CMD/SUPERFOO->(lq)
- $ -- LAMBDA
- $$ -- LAMBDA
- X -- ---
- Y -- ---
-
-
-
-
- - 86 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- When working with functional directories, one should keep
- in mind that $ is not the current directory itself; it is
- only a variable which is bound to the current directory. We
- could have obtained the same result in the above example by
- saying:
-
-
- /SYS/CMD/SUPERFOO->(def (eval $) (lambda (x y) (+ x y)))
-
- The call to EVAL inside the call to DEF is necessary because
- DEF does not evaluate its arguments, and we want the value
- of $, not $ itself.
-
-
-
-
-
-
- 6.15 Summary of Directory Management Functions
-
-
- These functions deal with the PDLISP directory structure.
-
-
- ADD-TO-PATH LAMBDA (NEWDIR)
-
- If NEWDIR is not already on the reader's search path,
- then this function adds it. Otherwise, nothing happens.
- In either case, the new reader search path is returned.
-
-
- CD CSUBR (NEWDIR)
-
- Stands for "Change Directory." The current directory is
- changed to the value of NEWDIR. NEWDIR must evaluate to a
- symbol, or an error results.
-
-
- CDQ NLAMBDA (NEWDIR)
-
- Similar to CD, except that it quotes (i.e., does not
- evaluate) its argument.
-
-
- DEF$ CNSUBR (Y)
-
- Sets the function definition cell of the current directory
- to Y, which is not evaluated. This function is equivalent to
- saying (DEF $ Y), where $ is the current directory during the
- evaluation of this function. Use of this function makes the
-
-
-
- - 87 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- current directory a functional directory, which is a
- short-hand way of saying that it is defined as both a
- function and as a directory. The function is defined using
- the symbol's function definition cell, and the directory
- value is defined using its value cell. The value returned
- by this function is the current directory.
-
-
- DIR LAMBDA (&optional SOMEDIR)
-
- This is a primitive directory listing function. DIR returns
- the value of SOMEDIR, which must be a directory. This value
- is a list of all of the symbols (user-defined atoms) which
- reside in the directory. If SOMEDIR is absent, then the value
- of the present directory is returned.
-
-
- DIRQ NLAMBDA (&optional SOMEDIR)
-
- Identical to DIR, except that SOMEDIR is quoted.
-
-
- GETPATH LAMBDA ()
-
- GETPATH returns the current value of the reader search
- path. For example,
-
- /USR/LOGIN->(getpath)
- (CMD/ CONST/)
-
- The slashes after CMD and CONST, of course, indicate
- that they are directories.
-
-
- GLOBAL CSUBR (X)
-
- Makes X, which must be a user-defined symbol, a global
- symbol. Global symbols can be found by the reader even if
- they are not in the current directory, as long as they are in
- a directory which lies along the reader search path.
-
-
- GLOBALP CSUBR (X)
-
- Returns T if X is a global symbol; otherwise returns NIL.
-
-
- LOCAL CSUBR (X)
-
- Makes X, which must be a symbol (user-defined atom), a local
-
-
-
- - 88 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- symbol. Local symbols are only visible to the PDLISP reader
- if they reside in the current directory; otherwise, the
- symbol is invisible, even if it resides in a directory on the
- reader search path. See SETASP, GLOBAL, LOCALP, GLOBALP.
-
-
- LOCALP CSUBR (X)
-
- Returns T if X is a private symbol; otherwise returns NIL.
- See LOCAL, GLOBAL, GLOBALP.
-
-
- LQ NLAMBDA (&OPTIONAL DIRECTORY)
-
-
- Prints out a listing of the symbols in DIRECTORY, with a
- line of information about each one. DIRECTORY is optional,
- and defaults to the current directory. The information is
- printed out in 3 columns, as follows:
-
- Column 1 is the name of the symbol. If the underscore
- prefix is set, as is the case with the distributed system,
- then all of the symbols are printed out with a leading
- underscore.
-
- Column 2 pertains to the variable or directory binding of
- the symbol. If the symbol is a global symbol, then the letter
- "g" is output. Otherwise, a dash ("-") is output. Immediately
- following, if the symbol is bound as a variable, then the
- letter "v" is output. If the symbol is bound as a directory,
- then the letter "d" are output. Otherwise, a dash is output.
-
- Column 3 pertains to the functional binding of
- the symbol. If the symbol is bound as a function, then
- the type (or "discipline") of the function declaration
- is shown. The possible values are: CSUBR, CNSUBR, SUBR,
- NSUBR, LAMBDA, NLAMBDA, and MACRO. For an explanation
- of each type, consult the beginning of this section.
-
- As an example, suppose that we typed in the following:
-
- /USR/LOGIN->(lq /sys/cmd)
-
- $ -v ---
- $$ -v ---
- % g- CSUBR
- * g- CSUBR
- *BACKQUOTE1 g- LAMBDA
- ...
-
-
-
-
- - 89 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- (many more functions and variables)
-
- ...
-
- T ; until finally lq returns T as its value.
-
- MCD CSUBR (X)
-
- Stands for "Make and Change Directory." This function is
- equivalent to (CD (MD X)).
-
-
- MCDQ CSUBR (X)
-
- Same as MCD, except that it does not evaluate its argument.
- This function is equivalent to (CD (MDQ X)).
-
-
- MD CSUBR (X)
-
- Stands for "Make Directory." The symbol X is created if it
- did not already exist at read-time, and it is made into a
- directory if it is not already defined as a variable,
- function, or something else. No error occurs if X is
- already defined as a directory. This function returns X if
- successful, NIL otherwise.
-
-
- MDQ CNSUBR (X)
-
- Same as MD, except that the argument is not evaluated.
-
-
- PARENT CSUBR (ASYMBOL)
-
- Returns the parent directory of ASYMBOL. The parent directory
- of / (root) is /.
-
-
- PATHLST CSUBR (ASYMBOL)
-
- Returns a list representing the path-name of ASYMBOL.
- Each symbol in the list is a directory symbol along the
- path of the symbol from the root.
-
-
- PATHNME CSUBR (ASYMBOL)
-
- This function digs out the path-name of ASYMBOL and
- returns it as a list. For example, if we were currently
-
-
-
- - 90 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- in the directory /FOO/BAR, and we wished to get the
- path-name of /FOO/BAR/BAZ, then we could type:
-
- /FOO/BAR->(pathnme 'baz)
- (FOO BAR BAZ)
-
-
- PATHSTR CSUBR (ASYMBOL)
-
- This function is similar to PATHNME, above, except that
- the path-name of ASYMBOL is returned as a string.
-
-
- PD LAMBDA (ASYMBOL)
-
- Changes the current directory to be ASYMBOL, and saves
- the old directory on a stack. The previous directory can
- be restored by POPD.
-
-
- PDQ NLAMBDA (ASYMBOL)
-
- Same as PD, except that its argument is not evaluated.
- Source is in dirlib.l.
-
-
- POPD LAMBDA ()
-
- Pops the directory stack. The current directory is changed
- to whatever was on the top of the directory stack. See PD
- and PDQ. Source is in dirlib.l.
-
-
- POPPATH NLAMBDA ()
-
- Pops a directory off the front of the reader-search-path.
- Source is in dirlib.l. See PUSHPATH.
-
-
- PUSHPATH LAMBDA (DIRECTORY)
-
- Pushes a directory onto the front of the reader-search-path.
- The argument must be a directory, or an error is generated.
- Source is in dirlib.l. See POPPATH.
-
-
- RM CSUBR (X)
-
- Stands for ReMove object; the specified object is removed from
- the PDLISP object list, and if nothing else in the system
-
-
-
- - 91 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
- points to it, it will be recycled as fresh storage.
-
-
- RMDIR LAMBDA (X)
-
- Stands for ReMove Directory; the specified directory symbol, X,
- is removed from the PDLISP object list. If X is present on
- the reader's search path, it will be deleted from same.
-
-
- RMDIRQ NLAMBDA (X)
-
- Similar to RMDIR, but quotes its argument.
-
-
- RMQ CNSUBR (X)
-
- Similar to RM, but quotes (i.e., does not evaluate) its argument.
-
-
- SETPATH LAMBDA (X)
-
- SETPATH sets the reader search path to X, and returns the
- new value. For example,
-
- /USR/LOGIN->(setpath '(/usr/fred /sys/cmd /sys/const))
- (FRED/ CMD/ CONST/)
- SRMDIR CSUBR (X)
-
- Stands for System RMDIR; this primitive is called by RMDIR.
- In general, this function should be avoided in favor of RMDIR
- or RMDIRQ, since it does not check if the directory to be
- removed is present on the reader's search path.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 92 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 93 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 94 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual PDLISP Directory Structure
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 95 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
-
-
-
-
-
- Chapter 7
-
- Control Constructs
-
-
-
- This chapter contains a description of functions which are
- useful in directing the "control flow" of LISP programs.
-
-
-
-
-
- 7.1 Explicit Evaluation
-
-
-
- Functions are provided for explicit evaluation in
- order to allow manual control of the evaluation process.
- For example, if FOO were a special form which evaluated
- its arguments in some idiosyncratic way, we might wish
- to explicitly evaluate them using one of these functions
- before FOO was applied.
-
- APPLY CSUBR (FN ARGLIST)
-
- Returns the result of the application of FN to the list
- of arguments, ARGLIST. FN can be any function which is
- not defined as a MACRO. ARGLIST must be a list (or NIL).
-
- for example:
- /USR/LOGIN->(setq fred '+)
- +
- /USR/LOGIN->(apply fred '(1 2))
- 3
- /USR/LOGIN->(apply 'cons '((+ 2 3) 4))
- ((+ 2 3) . 4) ;note that the result is not (5 . 4)
-
- APPLY arranges things so that the individual arguments
- in ARGLIST are not evaluated before FN is applied, even
- if FN is a CSUBR or LAMBDA, which ordinarily evaluate
- their arguments. See FUNCALL, EVAL, and QUOTE.
-
-
-
-
-
- - 96 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
- EVAL CSUBR (FORM)
-
- Allows explicit evaluation of a form. (EVAL FORM) returns
- the evaluation of FORM.
-
-
-
-
-
-
- 7.2 Conditional Evaluation
-
-
- Conditionals are special forms which perform the same
- function as the "if-then" or "if-then-else" statement in
- other languages. The simplest of these is the IF construct,
- and the most general is COND.
-
-
- IF CNSUBR (TEST IF-CASE &OPTIONAL ELSE-CASE)
-
- IF performs the following sequence of operations: First,
- TEST is evaluated. If it evaluates to a non-NIL value, then
- IF-CASE is evaluated, and the result is returned. If TEST
- evaluated to a NIL value, then if an ELSE-CASE parameter was
- supplied, it is evaluated and the result is returned.
- Otherwise, a value of NIL is returned by this function.
-
-
-
-
- COND CNSUBR (&REST CLAUSES)
-
- COND is the traditional conditional function supplied with
- LISP implementations. A call to COND contains a sequence of
- clauses, each of which consists of a test followed by none,
- one, or more consequents. That is, each clause is of the
- form:
-
-
- (TEST CONSEQUENT-1 CONSEQUENT-2 ... CONSEQUENT-N)
-
- As an example of a COND form, we could have:
-
-
- (cond (a b c) ;a clause with multiple consequents
- (d) ;a clause with no consequents
- (t e)) ;fall-through case
-
- COND evaluates the TEST part of each of its clauses in order
-
-
-
- - 97 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
- until it encounters one which does not evaluate to NIL. COND
- then evaluates each consequent of that clause, and returns
- the value of the last one. For example, suppose that in the
- code fragment above, that A did not evaluate to NIL. Then,
- COND would evaluate B and C, in that order, and finally
- return the value of C. The other clauses would not be
- evaluated.
-
- In the case that a TEST evaluates to a non-NIL value, and
- the clause contains no consequents, COND returns the value
- of TEST (which must, by definition, be non-NIL).
-
- If no TEST evaluates to a non-NIL value, and the COND
- "runs off the end" of its clause list, then a value of NIL
- is returned. As a matter of programming style, it is
- probably a good idea to make the TEST of the last clause the
- constant T. In this way, one can be sure that the COND
- explicitly returns a value.
-
- The PDLISP COND is Common LISP compatible.
-
-
-
-
-
-
- 7.3 DO and DO*
-
-
-
- DO MACRO (INIT TEST &REST BODY)
-
-
- Iterative control construct. The syntax is a subset of the
- Common LISP syntax. A DO contains 3 parts, INIT, TEST, and
- a BODY.
-
- INIT is the initialization component, which consists of a
- list of pairs of local variables and their initialization
- values. Each variable is bound to its initialization value
- upon entering the DO, and is restored to its entry value
- upon exiting the DO. If a local variable is specified
- without an initialization value, then it is initialized to
- NIL. If there are no local variables, then INIT must be NIL
- or (). Initialization of local variables takes place in
- parallel, so that each variable is initialized
- independently.
-
- The first part of TEST, which must be a list, is the
- termination test for the DO. After the termination test can
-
-
-
- - 98 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
- be any number of additional forms. Each time that the top
- of the loop is entered, the termination test is evaluated.
- If the termination test evaluates to T, then the rest of the
- forms in TEST are evaluated, and the value of the last one
- is returned as the value of the DO.
-
- BODY is a sequence of forms which are evaluated
- sequentially. After each form is evaluated, its value is
- discarded, so the only reason to include anything here would
- be for the side effects which might occur.
-
- As an example of the use of a DO, consider the function
- NTHCDR, which is defined in the file, "misc.l" on the
- distribution disk. NTHCDR is an implementation of the Franz
- LISP function by the same name. The job of NTHCDR is to CDR
- down a list (called 'E' here) N times. So, (NTHCDR 3 E)
- would stand for (CDR (CDR (CDR E))).
-
-
- (defun nthcdr (n e)
- (do ((i 0)) ;initialize i to 0.
- ((eql i n) e) ;termination test.
- ;
- ; body of DO starts here.
- ;
- (setq i (+ i 1)) ;increment i.
- (setq e (cdr e)))) ;cdr down e.
-
- The actual DO, of course, is nested inside of a function
- definition in this case. The INIT part of the DO consists of
- the form ((i 0)). Here, i is our counter variable. If we had
- needed more than one variable here, we could have written this
- part as, say, ((i 0) (j 2) (k 1)).
-
- The TEST part of the DO consists of the expression
- ((eql i n) e). Each time that the evaluator makes a pass
- through the DO, the expression (eql i n) is evaluated.
- If it evaluated to T, then the value of the expression e
- is returned.
-
- The body of the DO consists of the rest of the function
- definition, namely, (setq i (+ i 1)) and (setq e (cdr e)).
- These forms are each evaluated once each time through the
- DO, until the termination test returns T.
-
- If the PDLISP DO were to be fully compatible with the
- Common Lisp standard, then the init part would consist of
- ((vbl_1 init_value_1 step_1) (vbl_2 init_value_2 step_2) ... ).
- I will be extending the DO macro in a future release so
- that it implements all of the Common LISP standard.
-
-
-
- - 99 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
-
- DO* MACRO (INIT TEST &REST BODY)
-
-
- DO* works just like DO, except that the local variables are
- initialized sequentially, instead of in parallel as DO
- does. So, DO* is useful if there is a desirable dependency
- between local variables in the initialized varible list
- (INIT). The remarks on Common Lisp compatibility which are
- noted above under the DO macro also apply here.
-
-
-
-
-
-
- 7.4 Mapping Functions
-
-
-
- MAPCAR CSUBR (FN LIST1 &rest LISTS)
-
- MAPC LAMBDA (FN LIST1 &rest LISTS)
-
- MAPCAN CSUBR (FN LIST1 &rest LISTS)
-
- MAPCON CSUBR (FN LIST1 &rest LISTS)
-
- MAPLIST CSUBR (FN LIST1 &rest LISTS)
-
- MAPL LAMBDA (FN LIST1 &rest LISTS)
-
- Mapping is a form of iteration, which is a bit of technical
- jargon meaning "to repeat." The mapping functions described
- in this section are useful when the same function is to be
- applied repeatedly on lists of things. For example, suppose
- that we wished to add 1 to each element of a list of
- numbers. We could do the job with MAPCAR as follows:
-
-
- /USR/LOGIN->(MAPCAR 'ADD1 ;function to be applied
- '(1 3 5)) ;arguments to the function
- (2 4 6) ;voila!
-
- MAPCAR can also be used to apply functions which take more
- than 1 argument. However, if such is the case, then there
- must be exactly as many argument lists in the call to MAPCAR
- as the function specifies in its formal parameter list. For
- example, we could add two lists of arguments, as follows:
-
-
-
- - 100 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
-
- /USR/LOGIN->(mapcar '+ '(1 3 5) '(2 4 6))
- (3 7 11) ;list of sums
-
- In the above example, 2 argument lists were supplied, but +
- can take any number of arguments. So, we could have
- supplied 3, 4, or more argument lists, and they would all
- have been fed to +. There is no limit in PDLISP to the
- number of argument lists which can be supplied to MAPCAR or
- to any other mapping function.
-
- MAPC and MAPL are similar to MAPCAR and MAPLIST,
- respectively, except that they do not accumulate their
- arguments. These functions return as their values the first
- list argument passed, and are used when the mapping is being
- done primarily for the side effects which may occur.
-
- MAPCAN and MAPCON are like MAPCAR and MAPLIST,
- repectively, except that they accumulate their result by
- using NCONC instead of CONS. That is,
-
-
- (MAPCAN FN X1 ... XN) <==> (APPLY 'NCONC (MAPCAR FN X1 ... XN))
-
- (MAPCON FN X1 ... XN) <==> (APPLY 'NCONC (MAPLIST FN X1 ... XN))
-
- One should keep in mind, however, that MAPCAN and MAPCON are
- destructive functions, because they use NCONC. Also, an
- error will be generated unless FN consistently returns
- lists, because NCONC will choke on arguments which are not
- lists.
-
- The function which is supplied to a mapping function must
- be something which could be given to APPLY; in particular it
- cannot be a MACRO. However, there are no restrictions as to
- its formal parameter list - it could have &OPTIONAL, &REST,
- and/or &AUX parameters.
-
-
-
-
-
-
- 7.5 PROG and Friends
-
-
-
- PROG MACRO (VBL_LIST &REST BODY)
-
-
-
-
- - 101 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
- PROG is variously described as a crutch or as a
- mainstay, depending upon one's vintage. Its original
- intent was to "sugar coat" the language so that LISP
- programmers could program in an imperative style if they
- so chose. However, as the school of "functional
- programming" has matured, more people are using DO,
- mapping functions, and special purpose MACROs in
- preference to it. With the advent of Common Lisp, PROG,
- which was once thought to be rightly implemented as a
- system primitive, is now usually implemented as a MACRO
- itself with no special privileges.
-
- The twist that Common Lisp has provided concerning
- PROG is that it has been broken down into 3 simpler
- operations: the binding of local variables, the use
- of the RETURN statement, and the use of the GO statement.
- These 3 operations have been distilled into independent
- constructs, namely, LET, BLOCK, and TAGBODY.
-
-
- TAGBODY CSUBR (&REST BODY)
-
- TAGBODY is the primitive form which executes
- imperative s-expression forms. A tag body consists
- of a sequence of elements. Each element of the tag
- body may be a symbol, in which case it is called a
- tag, or a list, in which case it is called a
- statement.
-
- TAGBODY proceeds through the tag body from left
- to right. Tags are skipped over; they are useful only
- as targets for calls to the GO function. Statements
- are evaluated as they are encountered, and the value
- produced by each is discarded.
-
- If the end of the tag body is reached, then TAGBODY
- returns a value of NIL. Otherwise, if an s-expression of
- the form (GO SOME_TAG) is encountered, then control resumes
- at the part of the body which immediately follows SOME_TAG.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 102 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
- BLOCK CNSUBR (NAME &REST BODY)
-
- BLOCK executes each form in BODY from left to right,
- and returns the value of the last form. However, if
- a RETURN is encountered, then the value specified by
- the RETURN is taken to be the value to be returned
- by the BLOCK, and control proceeds as if the BLOCK
- had run to completion. BLOCK is similar to PROGN, except
- that PROGN is invisible as far as RETURN is concerned;
- RETURN only has meaning with respect to a BLOCK.
-
- The PDLISP BLOCK construct is actually a subset of the
- full Common Lisp standard, and will be upgraded in a later
- release. In particular, the Common standard specifies that
- the scope of a BLOCK construct be determined lexically, but
- all of the lexical binding machinery was not working in the
- first release. Also, Common specifies that blocks can be
- named, but the RETURN-FROM function has not yet been
- implemented in PDLISP; consequently named BLOCKs should be
- avoided at the present time. This should not create an
- immediate problem, because all of the macros provided with
- PDLISP which expand into BLOCKs do so into BLOCKs named
- NIL, which works with RETURN. See Steele [1984] for more
- information.
-
-
- LET CNSUBR (INIT_LIST &REST BODY)
- LET* CNSUBR (INIT_LIST &REST BODY)
-
- These constructs are provided in order to control
- lambda-binding transactions. In the following descriptions,
- INIT_LIST is a list of variable-value pairs, and BODY
- is a list of s-expressions to be evaluated.
- In particular, the usage of LET is:
-
- (LET ((VARIABLE_1 VALUE_1)
- (VARIABLE_2 VALUE_2)
-
- ...
-
- (VARIABLE_N VALUE_N))
- BODY)
-
-
-
-
-
-
-
-
-
-
- - 103 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
- In evaluating a LET, PDLISP follows the following
- sequence of operations:
-
- (1) the forms VALUE_1, VALUE_2, and so on through VALUE_N
- are evaluated, and the corresponding values are saved.
-
- (2) all of the variables are bound simultaneously to
- their respective values.
-
- (3) the expressions comprising BODY are evaluated in sequence,
- and the value returned by the LET is that of the last
- expression in BODY; in effect, BODY is evaluated as
- an implicit PROGN, which is described below.
-
- The evaluation of a LET* is identical to that of a LET,
- except that the variables are bound to their respective
- values sequentially, instead of in parallel. This permits
- the value of a initialized variable to depend upon previous
- ones in INIT_LIST.
-
- INIT_LIST can contain uninitialized variables, as well.
- For example, if instead of the variable-value pair (FOO BLUE),
- INIT_LIST contained simply FOO, then FOO would be initialized
- to the default value of NIL. In general, however, this decreases
- the clarity of the code, because then one has to look inside
- of BODY to see if the variable is SETQ'd before its value
- is referenced.
-
- A PROG consists of two parts, a list of (possibly)
- initialized variables, and a body of s-expressions to
- be executed. In my description of the PROG syntax,
- I have identified these two parts, as VBL_LIST and
- BODY. BODY is a &REST parameter to indicate that
- the first parameter to PROG is interpreted to be VBL_LIST,
- and that the rest of the argument list is interpreted
- as BODY. BODY is just interpreted as a tag body in the
- description of TAGBODY, above.
-
- Now, let's see how PROG puts all of this together.
- Consider the following function, which computes N to the
- Mth power; never mind for now that the function could be
- more elegantly coded in another style:
-
-
-
-
-
-
-
-
-
-
- - 104 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
- ;
- ; ipower - iteratively coded n ^ mth power routine
- ; m and m must both be integers.
- ;
- (defun ipower (m n)
- (prog ((result 1) (exponent n))
- ;
- ; In the VBL_LIST, above,
- ; result is initialized to 1
- ; and exponent is initialized to n
- ;
- ; now for the BODY:
- ;
- ploop (cond ((zerop exponent) (return result))) ;test
- (setq result (* m result)) ;reset
- (setq exponent (- exponent 1)) ;reset
- (go ploop))) ;repeat
-
- Let's examine the control flow of IPOWER.
- First, two local variables are declared and initialized.
- Namely, RESULT, which is a temporary variable which
- accumulates the value to be returned from this function,
- is initialized to 1, and EXPONENT is initialized to N.
-
- After initialization, the main body, which happens
- to be a loop, is executed. First, a COND statement checks
- to see if EXPONENT has reached 0. If it has, then RESULT
- is immediately returned. Otherwise, control flow "falls
- through" the COND, and the iterative section is entered.
- RESULT is multiplied by M another time, EXPONENT is
- decremented, and control is transferred back to the test
- at the top of the loop. Notice that in the degenerate
- case that the parameter N is 0, the test at the top
- of the loop immediately goes off, and the main section
- of the loop is never executed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 105 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
- When the PROG macro for IPOWER is expanded, something
- like the code below is actually produced:
-
- (ipower (lambda (m n)
- (block 'nil ;a BLOCK
- (let ((result 1) ;with a name of NIL
- (exponent n)) ;surrounds a LET
- (tagbody ;all wrapped around a TAGBODY
- ;
- ; BODY of the tag body is below:
- ;
- ploop (cond ((zerop exponent) (return result)))
- (setq result (* m result))
- (setq exponent (- exponent 1))
- (go ploop))))))
-
- For the curious, the actual definition of the PROG macro is
- in MISC.L. Incidently, the above example could have been
- quite neatly coded as a DO. I suggest that you attempt to do
- so. The answer is in the file EXAMPLES.L, and is called
- DO_IPOWER.
-
-
-
-
- PROG* MACRO (VBL_LIST &REST BODY)
-
- PROG* works just like PROG, except that the local variables
- in VBL_LIST are initialized sequentially, instead of in
- parallel, so that dependencies between local variables
- can be processed. PROG* has the same relationship to PROG as
- LET* has to LET. So, we could write:
-
- (prog* ((x t) (y (cdr x)))
- (return y))
-
- and the result would be the CDR of X.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 106 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
-
-
-
- 7.6 PROGN and PROG1
-
-
-
- PROGN CNSUBR (&REST SEQUENCE)
-
- Evaluates a sequence of s-expressions, and returns the value
- of the last one. For example,
-
- (progn
- (setq a 4)
- (setq b 5)
- (+ a b))
-
- would evaluate to 9. In addition, A would be EQL to 4,
- and B would be EQL to 5.
-
- PROG1 CNSUBR (&REST SEQUENCE)
-
- Similar to PROGN, except that it returns the value of the
- first s-expression in the sequence.
-
-
-
-
- 7.7 Implicit PROGN
-
-
- Many PDLISP/Common LISP special forms such as COND evaluate
- sequences of s-expressions as if they were clauses of a
- PROGN. For example, we could write a COND as follows:
-
-
- (cond
- ((atom a) (princ "found an atom") t)
- (t (princ "no dice")))
-
- Function definitions can also be implicit PROGN's, as
- follows:
-
-
- (defun foo (x y)
- (setq a (+ x y))
- (setq b (* x y))
- y)
-
-
-
-
- - 107 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
- Clever hackers may notice that the usage of an explicit
- PROGN when an implicit one would suffice wastes a node when
- the expression is being interpreted. However, no such waste
- occurs when the expression is compiled, because all
- s-expressions which are compiled are removed from
- s-expression space. Consequently, I recommend that PROGN be
- used explicitly whenever it augments the readability of an
- expression.
-
-
-
-
-
-
- 7.8 LOOP
-
-
-
- LOOP MACRO (&REST FORM)
-
- LOOP provides a simple and clean way to perform iteration.
- FORM is repeatedly evaluated as an implicit PROGN. This
- computation continues indefinitely. LOOP is actually
- implemented as a MACRO which wraps a BLOCK with the name of
- NIL around the PROGN. The only way for the LOOP to be exited
- is by way of a RETURN to the surrounding BLOCK. Programmers
- should not confuse the PDLISP/Common LISP LOOP with
- constructs of the same name in other dialects; they are
- generally MACROs which perform the same general purposes as
- the PDLISP/Common DO.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 108 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
-
-
-
- 7.9 CATCH and THROW
-
-
-
- CATCH CNSUBR (TAG &REST FORM)
-
- This is a superset of the Common LISP CATCH function.
- TAG is normally a symbol or a list of symbols. FORM can
- be any form, or a list of forms (CATCH evaluates FORM
- as an implicit PROGN). CATCH employs the following sequence
- of operation:
-
- (1) TAG is evaluated.
-
- (2) FORM is evaluated.
-
- (3) If FORM evaluated normally, then its value is returned.
-
- (4) If, however, a call to THROW occurred during the evaluation
- of FORM, then the tag of the THROW is compared with the tag
- of the CATCH. The value passed to THROW is returned by
- CATCH if one of the following situations holds:
- (a) TAG is a symbol, and the tag of the THROW is EQ
- to it,
- (b) TAG is a list, and the tag of the THROW is EQ
- to a member of it,
- or (c) TAG is NIL.
-
- (5) If a call to THROW occurred during the evaluation of
- of FORM, but the tag which was thrown did not come under
- one of the cases listed in (4), above, then an error
- may have occurred, or there may have been another call to
- CATCH involved.
-
- PDLISP follows the Common LISP standard as far as the
- syntax of CATCH and THROW go. Programmers hopping between
- different LISP dialects should keep in mind that system
- implementors have a diabolical tendency to swap TAG and FORM
- in their syntax.
-
- THROW CNSUBR (TAG X)
-
- X is returned through the closest dynamically enclosing CATCH
- which has the tag TAG. See CATCH.
-
-
-
-
-
- - 109 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
-
-
-
- 7.10 Error Handling in PDLISP
-
-
- When an error occurs in PDLISP, the evaluator observes the
- following procedure:
-
-
- (1) The control stack is searched to see if there is an
- enclosing instance of ERRSET. If there is, then control
- is transferred to it, and a value of NIL is returned
- from the ERRSET.
-
- (2) If there is no such ERRSET, then the system break hook
- is examined. If the system break hook, which can be
- examined and set using the STATUS function, is non-NIL,
- then control is transferred to it.
-
- (3) Otherwise, the internal break handler is entered, and
- a prompt such as "<1>" is output. The internal break
- handler is just a "read-eval-print" loop, except that
- the state of the computation is frozen at the point at
- at which the error occurred. This allows the user to
- examine and modify variables and function definitions
- at will. The loop is exited by typing the form (RETURN X),
- where X is some form. This form will be returned by the
- evaluator as the value of the computation which was frozen.
- It is also possibleto return directly to the top-level
- driver loop by entering the form (RESET).
-
- Normally, an ERRSET is not used in development under
- PDLISP. This allows invocation of the break handler when an
- error occurs. Otherwise, when an application (such as an
- editor) is written, it is enclosed inside of an ERRSET so
- that the user of the application is insulated from errors
- when they occur. In fact, this can be taken as the
- practical definition of an application in PDLISP.
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 110 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
- It is possible to "trick" the system and simulate an
- internal error which will be treated as if it were generated
- by the interpreter itself. This can be accomplished using
- the ERR function. This function takes one argument, which
- is usually a string which should be printed out at the
- console when the error occurs. For example, we could define
- a function foo as:
-
-
- (defun foo (x)
- (cond ((not (fboundp x))
- (err "***> FOO: arg not bound as a function.")))
- (t (frotz (bar 'baz))))
-
- Whether or not the error message is printed is controlled by
- the global variable *PRINT_ERR_MESSAGES* which is created in
- the file "error.l". The initial value of this variable is T,
- which causes all messages generated by instances of ERR to
- be printed.
-
-
- ERR LAMBDA (X)
-
- This function causes a "simulated error", which will be
- intercepted by the interpreter. If there is an enclosing
- instance of ERRSET, then control is transferred to it.
- Otherwise, normal error-handling procedures are followed. In
- actuality, this function is defined as in the file "error.l".
- See the text for more info.
-
-
- ERRSET LAMBDA (X)
-
- This function normally returns a list of one element, which
- is the result of the evaluation of X. If an error occurs
- during the evaluation of X, then evaluation will terminate
- and a value of NIL is returned. If a "simulated error" occurs
- during the evaluation of X, which can only occur through a
- call to ERR, then this function returns as its value the form
- which was passed to ERR. This function is defined in the file
- "error.l".
-
-
-
-
-
-
-
-
-
-
-
-
- - 111 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 112 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Control Constructs
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 113 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Property Lists
-
-
-
-
-
-
-
-
-
-
- Chapter 8
-
- Property Lists
-
-
-
- Since prehistoric times, LISP implementations have provided
- property lists, or plists for short, to associate
- miscellaneous information with symbols. A property list is
- a list of ordered pairs of indicators and values. All of the
- functions in the property list management system use the
- indicator as a key for search purposes.
-
- In PDLISP, property lists are implemented as lists of
- dotted pairs, where each dotted pair is an indicator-value
- pair. However, this implementation will probably be
- rewritten in a future release for Common LISP
- compatibility.
-
-
-
-
-
-
- 8.1 GET, PUTPROP, and REMPROP
-
-
- The three basic functions for manipulating property lists
- are GET, PUTPROP, and REMPROP. GET retrieves the value
- associated with an indicator on a property list; PUTPROP
- stores a value under an indicator; and REMPROP removes an
- indicator-value pair from a property list.
-
-
-
-
- GET CSUBR (SYMBOL INDICATOR)
-
- GET returns the current value associated with INDICATOR
- on the property list of SYMBOL.
-
-
-
-
-
-
-
- - 114 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Property Lists
-
-
-
-
-
- PUTPROP CSUBR (SYMBOL VALUE PROPERTY)
-
- Puts the pair (PROPERTY, VALUE) on the property list of
- SYMBOL. Any previous association between PROPERTY and VALUE
- under SYMBOL is destroyed. PROPERTY and VALUE can be
- arbitrary s-expressions, as PDLISP uses EQUAL to detect
- equality when searching property lists.
-
-
- REMPROP CSUBR (SYMBOL PROPERTY)
-
- Removes a property-value pair from the property list of
- SYMBOL. A subsequent (GET SYMBOL PROPERTY) will return NIL.
- All occurences of PROPERTY on SYMBOL's property list are
- removed, since there could exist multiple PROPERTY-VALUE
- pairs if PUSHPROP had been used.
-
-
-
-
-
- 8.2 SYMBOL-PLIST and SETPLIST
-
-
-
- SYMBOL-PLIST CSUBR (SYMBOL)
-
- Returns the beginning of the property list for SYMBOL.
-
-
- SETPLIST CSUBR (SYMBOL VALUE)
-
- Sets the property list for SYMBOL to value. This function
- returns T if no error occurred, NIL otherwise.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 115 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Property Lists
-
-
-
-
-
-
-
-
- 8.3 PUSHPROP and POPPROP
-
-
-
- The following functions may go away in the next release
- if I cannot implement a Common LISP - style property list
- system with them being present:
-
-
- PUSHPROP CSUBR (SYMBOL VALUE PROPERTY)
-
- Similar to PUTPROP, except that the property list for SYMBOL
- is considered to be a stack. Any (PROPERTY, VALUE) pair which
- was previously on the property list of SYMBOL will be left
- intact, and can be recovered by a subsequent POPPROP.
-
-
- POPPROP CSUBR (SYMBOL PROPERTY)
-
- Undoes a PUSHPROP. If there is more than one PROPERTY-VALUE
- pair on the property list of SYMBOL, then the one which
- was most recently pushed (using PUSHPROP) is removed.
- The next one on the property list becomes visible to GET.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 116 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Property Lists
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 117 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Property Lists
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 118 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
-
-
-
-
-
- Chapter 9
-
- Input and Output
-
-
-
- The follow functions are presently provided for I/O. They
- will be expanded in future releases.
-
-
- LOAD CSUBR (STR)
-
- Causes PDLISP to silently read input from a file with
- a file system name of STR. As each s-expression is read,
- it is evaluated. Returns a value of T if no error occurred,
- otherwise NIL.
-
-
- LOADV CSUBR (STR)
-
- Instructs PDLISP to read input from a file. The "V"
- in the function name indicates "verbosity", and the
- result of the evaluation of each s-expression is printed
- out on the terminal as the file is read in. Returns
- a value of T if no error occurred, otherwise NIL.
-
-
- PP CSUBR (X &OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Pretty-prints an s-expression. The source for this
- function is in fmtio.l, should anyone wish to modify it.
-
-
- PPDEF CSUBR (X &OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Pretty-prints the functional definition of a symbol,
- if one exists.
-
-
-
-
-
-
-
-
- - 119 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- PRINC CSUBR (X &OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Prints an expression on the output stream.
- The expression is printed verbatim; i.e., any strings
- are output with quote marks surrounding them.
-
-
- PRINT CSUBR (X &OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Prints an expression on the output stream.
- Any strings in the expression are printed without
- surrounding quote marks.
-
-
- PTOSTR CSUBR (X &OPTIONAL MODE)
-
- Prints an s-expression to a string, which is returned.
- If MODE = T, then the output is done using PRINC;
- otherwise, PRINT is used.
-
-
- READ CSUBR (&OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Reads an s-expression from the standard input,
- or a stream if HANDLE is specified.
-
-
- TERPRI CSUBR (&OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Stands for "terminate the print line". The optional
- parameter is a file handle. If it is present, output
- is sent to the named stream; otherwise, output is sent
- to the standard output.
-
-
- UNPRINT CSUBR (X &OPTIONAL HANDLE)
- or () (rev 1.0)
-
- Same as PRINT, except that the pretty-printer is bypassed,
- regardless of whether or not the pretty-printer hook has
- been set. See PRINT, STATUS, PP_HOOK.
-
-
-
-
-
-
-
- - 120 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
-
-
-
- 9.1 Console I/O
-
-
- This section will be available with release 2.0.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 121 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 122 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 123 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
-
-
-
- 9.2 File I/O
-
-
- This section will be included with release 2.0, and will be
- available as an update. See /SYS/NEWS for more info.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 124 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 125 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 126 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
-
-
-
-
-
- 9.3 The PDLISP Reader
-
-
- This section will be available as an update.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 127 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 128 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 129 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 130 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 131 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
-
-
-
-
-
- 9.4 Floating Point Formats
-
-
- The floating point output format is controlled via the
- "floating point format hook". Setting the floating point
- format hook is covered in the chapter on the STATUS function
- and system hooks.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 132 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 133 - Version 1.10
-
-
-
-
-
-
-
- PDLISP language manual Input and Output
-
-
-
-
-
- This page intentionally left blank
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - 134 - Version 1.10
-
-
-
-