That's probably the new property list functions done...
but too tired to test!
This commit is contained in:
parent
31d8f0b8f9
commit
64a27be8e5
354
doc/lisp1.5.md
354
doc/lisp1.5.md
|
@ -331,7 +331,7 @@ it is not A.
|
||||||
|
|
||||||
The main application of conditional expressions is in defining functions recursively.
|
The main application of conditional expressions is in defining functions recursively.
|
||||||
|
|
||||||
#### Example
|
#### Example - recursive function
|
||||||
|
|
||||||
`ff[x] = [atom[x] -> x; T -> ff[car[x]]]`
|
`ff[x] = [atom[x] -> x; T -> ff[car[x]]]`
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ The conditional expression is useful for defining numerical computations, as wel
|
||||||
```
|
```
|
||||||
|x| = [x<0 -> -x; T -> x]
|
|x| = [x<0 -> -x; T -> x]
|
||||||
```
|
```
|
||||||
The factorial of a nonhnegative integer can be defined by
|
The factorial of a non-negative integer can be defined by
|
||||||
```
|
```
|
||||||
n! = [n=0 -> 1; T -> n.[n-l]!]
|
n! = [n=0 -> 1; T -> n.[n-l]!]
|
||||||
```
|
```
|
||||||
|
@ -569,26 +569,32 @@ This can be translated into the following S-expression: ,
|
||||||
((QUOTE T)(QUOTE F)))))
|
((QUOTE T)(QUOTE F)))))
|
||||||
```
|
```
|
||||||
|
|
||||||
- sub st[^;^; z]
|
#### subst[x; y; z]
|
||||||
This function gives the result of substituting the S-expression x for all occurrences
|
|
||||||
of the atomic symbol y in the S-expression z. It is defined by
|
|
||||||
|
|
||||||
###### s~bst[x;~;z] = [eq~al[~;z] -- x;atom[z] - z;T - cons[subst
|
This function gives the result of substituting the S-expression x for all occurrences of the atomic symbol y in the S-expression z. It is defined by
|
||||||
|
|
||||||
```
|
```
|
||||||
|
subst[x; y; z] = [equal[y; z] -> x;
|
||||||
|
atom[z] - z;
|
||||||
|
T - cons[subst
|
||||||
[x; y; car[z]]; subst[x; y; cdr[z]]]]
|
[x; y; car[z]]; subst[x; y; cdr[z]]]]
|
||||||
```
|
```
|
||||||
|
|
||||||
As an example, we have
|
As an example, we have
|
||||||
|
|
||||||
SU~S~[(X. A);B;((A. B). c)] = ((A. (X. A)). C)
|
```lisp
|
||||||
null[x]
|
SUBST[(X . A); B; ((A . B) . c)] = ((A . (X . A)) . C)
|
||||||
This predicate is useful for deciding when a list is exhausted. It is true if and
|
```
|
||||||
only if its argument is NIL.
|
|
||||||
|
#### null[x]
|
||||||
|
This predicate is useful for deciding when a list is exhausted. It is true if and only if its argument is NIL.
|
||||||
|
|
||||||
The following functions are useful when S-expressions are regarded as lists.
|
The following functions are useful when S-expressions are regarded as lists.
|
||||||
|
|
||||||
1. append[x; y]
|
#### 1. append[x; y]
|
||||||
append[x; y] = [n~ll[x]-~; T-cons[car [x]; append[cdr [x]; y I]]
|
```
|
||||||
|
append[x; y] = [null[x] -> y; T -> cons[car [x]; append[cdr [x]; y]]]
|
||||||
|
```
|
||||||
|
|
||||||
An example is
|
An example is
|
||||||
|
|
||||||
|
@ -596,175 +602,193 @@ An example is
|
||||||
append[(A B);(C D E)] = (A B C D E)
|
append[(A B);(C D E)] = (A B C D E)
|
||||||
```
|
```
|
||||||
|
|
||||||
2. member[^;^]
|
#### 2. member[x; y]
|
||||||
This predicate is true if the S-expression x occurs among the elements of the
|
|
||||||
list y. We have
|
|
||||||
memberlx; y] = [null[y ]--F;
|
|
||||||
equal[x; car [y ]I--T;
|
|
||||||
T-member [x; cdr [y I]]
|
|
||||||
|
|
||||||
This function gives the list of pairs of corresponding elements of the lists x and
|
This predicate is true if the S-expression `x` occurs among the elements of the list `y`. We have
|
||||||
y, and appends this to the list a. The resultant list of pairs, which is like a table with
|
```
|
||||||
|
member[x; y] = [null[y] -> F;
|
||||||
|
equal[x; car [y ]] ->T;
|
||||||
|
T -> member[x; cdr [y ]]]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. pairlis[x; y; a]
|
||||||
|
|
||||||
|
<a name="page12">page 12</a>
|
||||||
|
|
||||||
|
This function gives the list of pairs of corresponding elements of the lists `x` and
|
||||||
|
`y`, and appends this to the list `a`. The resultant list of pairs, which is like a table with
|
||||||
two columns, is called an association list. We have
|
two columns, is called an association list. We have
|
||||||
|
|
||||||
```
|
```
|
||||||
pairlis [x; y; a] = [null[x]--a; T-cons[cons[car[x]; car[y]];
|
pairlis [x; y; a] = [null[x] -> a;
|
||||||
|
T -> cons[cons[car[x]; car[y]];
|
||||||
pairlis[cdr[x]; cdr [y]; a]]]
|
pairlis[cdr[x]; cdr [y]; a]]]
|
||||||
```
|
```
|
||||||
|
|
||||||
An example is
|
An example is
|
||||||
|
|
||||||
```
|
```
|
||||||
pairlis[(A B C);(U V w);((D. X) (E. Y))] =
|
pairlis[(A B C);(U V W);((D . X) (E . Y))] =
|
||||||
((A . U) (B . V) (C . W)(D . X) (E . Y))
|
((A . U) (B . V) (C . W)(D . X) (E . Y))
|
||||||
```
|
```
|
||||||
|
|
||||||
4. assoc[x; a]
|
#### 4. assoc[x; a]
|
||||||
If a is an association list such as the one formed by pairlis in the above example,
|
|
||||||
then assoc will produce the first pair whose first term is x. Thus it is a table searching
|
If `a` is an association list such as the one formed by `pairlis` in the above example,
|
||||||
|
then `assoc` will produce the first pair whose first term is `x`. Thus it is a table searching
|
||||||
function. We have
|
function. We have
|
||||||
|
|
||||||
|
```
|
||||||
|
assoc[x; a] = [equal[caar[a]; x] -> car[a]; T -> assoc[x; cdr[a]]]
|
||||||
|
```
|
||||||
|
|
||||||
An example is
|
An example is
|
||||||
|
|
||||||
```
|
```
|
||||||
assoc[~;((A. (M N)), (B. (CAR X)), (C. (QUOTE M)), (C. (CDR x)))]
|
assoc[B; ((A . (M N)), (B . (CAR X)), (C . (QUOTE M)), (C . (CDR x)))]
|
||||||
= (B. (CAR x))
|
= (B . (CAR X))
|
||||||
```
|
```
|
||||||
|
|
||||||
5. sublisla; y]
|
##### 5. sublis[a; y]
|
||||||
Here a is assumed to be an association list of the form ((ul. vl)... (un. v,)),
|
|
||||||
where the u1 s are atomic, and y is any S-expression. What sublis does, is to treat
|
Here `a` is assumed to be an association list of the form ((u<sub>1</sub>. v<sub>1</sub>)... (u<sub>n</sub> . v<sub>n</sub>)),
|
||||||
the u1 s as variables when they occur in y, and to substitute the corresponding v1 s
|
where the `u`s are atomic, and `y` is any S-expression. What `sublis` does, is to treat
|
||||||
from the pair list. In order to define sublis, we first define an auxiliary function.
|
the `u`s as variables when they occur in `y`, and to substitute the corresponding `v`s
|
||||||
We have
|
from the pair list. In order to define `sublis`, we first define an auxiliary function. We have
|
||||||
sub2[a; z] = [null[a]+z;eq[caar[a]; z]-cdar[a];~-
|
|
||||||
sub%[cdr[a]; z]]
|
```
|
||||||
|
sub2[a; z] = [null[a] -> z; eq[caar[a]; z] -> cdar[a];
|
||||||
|
T -> sub2[cdr[a]; z]]
|
||||||
|
```
|
||||||
and
|
and
|
||||||
sublis[a; y] = [at0rn[~]-sub2[a;~]; T-cons[sublis[a; car[^]];
|
|
||||||
sublis[a; cdr [Y]]]]
|
```
|
||||||
|
sublis[a; y] = [atom[y] -> sub2[a; y];
|
||||||
|
T -> cons[sublis[a; car[y]]; sublis[a; cdr[y]]]]
|
||||||
|
```
|
||||||
|
|
||||||
An example is
|
An example is
|
||||||
|
|
||||||
|
```
|
||||||
sublis[((X. SHAKESPEARE) (Y. (THE TEMPEST)));(X WROTE Y)] =
|
sublis[((X. SHAKESPEARE) (Y. (THE TEMPEST)));(X WROTE Y)] =
|
||||||
(SHAKESPEARE WROTE (THE TEMPEST))
|
(SHAKESPEARE WROTE (THE TEMPEST))
|
||||||
The universal function evalquote that is about to be defined obeys the following
|
|
||||||
identity. Let f be a function written as an M-expression, and let fn be its translation.
|
|
||||||
(& is an S-expression. ) Let f be a function of n arguments and let args=(argl...
|
|
||||||
argn), a list of the n S-expressions being used as arguments. Then
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The universal function `evalquote` that is about to be defined obeys the following identity. Let `f` be a function written as an M-expression, and let `fn` be its translation. (`fn` is an S-expression. ) Let `f` be a function of n arguments and let args=(arg<sub>1</sub>... arg<sub>n</sub>), a list of the `n` S-expressions being used as arguments. Then
|
||||||
|
|
||||||
|
`evalquote[fn; args] = f[arg`<sub>1</sub>`... arg`<sub>n</sub>`]`
|
||||||
|
|
||||||
|
<a name="page13">page 13</a>
|
||||||
|
|
||||||
if either side of the equation is defined at all.
|
if either side of the equation is defined at all.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
fi ~[[x;~];cons[car[x];y]]
|
|
||||||
fn: (LAMBDA (X Y) (CONS (CAR X) Y))
|
| | |
|
||||||
argl: (A B)
|
| --------------- | -------------------------------- |
|
||||||
arg2: (C D)
|
| f | λ[[x; y];cons[car[x]; y]] |
|
||||||
args: ((A B) (C D))
|
| fn | (LAMBDA (X Y) (CONS (CAR X) Y)) |
|
||||||
evalquote[(LAMBDA (X Y) (CONS (CAR X) Y)); ((A B) (C D))] =
|
| arg<sub>1</sub> | (A B) |
|
||||||
~[[x;y];cons[car[x];y]][(A B);(C Dl]=
|
| arg<sub>2</sub> | (C D) |
|
||||||
(A C D)
|
| args | ((A B) (C D)) |
|
||||||
evalquote is defined by using two main functions, called eval and apply. apply
|
|
||||||
handles a function and its arguments, while eval handles forms. Each of these func-
|
`evalquote[(LAMBDA (X Y) (CONS (CAR X) Y)); ((A B) (C D))] =`
|
||||||
tions also has another argument that is used as an association list for storing the val-
|
λ`[[x;y];cons[car[x];y]][(A B);(C D)] =`
|
||||||
ues of bound variables and f unction names.
|
`(A C D)`
|
||||||
|
|
||||||
|
`evalquote` is defined by using two main functions, called `eval` and `apply`. `apply` handles a function and its arguments, while `eval` handles forms. Each of these functions also has another argument that is used as an association list for storing the values of bound variables and function names.
|
||||||
|
|
||||||
|
*note here that the environment -- the combination of the object list and the pushdown list -- is said to be an assoc list, where, importantly, it isn't. Of course, for the simplest possible Lisp, it would be -- But (to my surprise) Lisp 1.5 is nothing like the simplest possible Lisp.*
|
||||||
|
|
||||||
|
```mexpr
|
||||||
|
evalquote[fn; x] = apply[fn; x; NIL]
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
|
||||||
where
|
where
|
||||||
|
```mexpr
|
||||||
apply[fn; x; a] =
|
apply[fn; x; a] =
|
||||||
```
|
[atom[fn] -> [eq[fn; CAR] -> caar[x]
|
||||||
|
eq[fn; CDR] -> cdar[x];
|
||||||
##### [atom[fn] - [eq[fn;~~~] - caar[x]
|
eq[fn; CONS] -> cons[car[x]; cadr[x]];
|
||||||
|
eq[fn; ATOM] -> atom[car[x]];
|
||||||
```
|
eq[fn; EQ] -> eq[car[x]; cadr[x]];
|
||||||
eq[fn;~~~] -- cdar[x];
|
T -> apply[eval[fn; a]; x; a]]
|
||||||
eq[fn; CONS] -- cons[car[x]; cadr[x]];
|
eq[car[fn]; LAMBDA] -> eval[caddr[fn]; pairlis[cadr[fn]; x; a]];
|
||||||
eq[fn;~~~~] -- atom[car[x]];
|
eq[car[fn]; LABEL] -> apply[caddr [fn]; x; cons[cons[cadr [fn];
|
||||||
eq[fn; EQ] - eq[car[x]; cadr[x]];
|
|
||||||
```
|
|
||||||
|
|
||||||
###### T - apply[eval[fn;a];x;a]]
|
|
||||||
|
|
||||||
eq[car[fn]; LAMBDA] -- eval[caddr [fn]; pairlis[cadr[fn];x;a]];
|
|
||||||
|
|
||||||
###### eq[car [fn]; LABEL] - apply [caddr [fn]; x; cons [cons[cadr [fn]
|
|
||||||
|
|
||||||
```
|
|
||||||
caddr[fn]]; a]]]
|
caddr[fn]]; a]]]
|
||||||
eval[e;a] = [atom[e] - cdr[assoc[e;a]];
|
|
||||||
|
eval[e;a] = [atom[e] -> cdr[assoc[e;a]];
|
||||||
|
atom[car[e]] -> [eq[car[e]; QUOTE] -> cadr[e];
|
||||||
|
eq[car[e]; COND] -> evcon[cdr[e]; a];
|
||||||
|
T -> apply[car[e]; evlis[cdr[el; a]; a]];
|
||||||
|
T -> apply[car[e]; evlis [cdr[e]; a]; a]]
|
||||||
```
|
```
|
||||||
|
|
||||||
###### atom[car[e]] -
|
`pairlis` and `assoc` have been previously defined.
|
||||||
|
|
||||||
```
|
```mexpr
|
||||||
[eq[car QUOTE] - cadr [el;
|
evcon[c; a] = [eval[caar[c]; a] -> eval[cadar[c]; a];
|
||||||
eq[car[e]; COND] - evcon[cdr [el; a];
|
T -> evcon[cdr [c];a]]
|
||||||
T -- apply[car [el; evlis[cdr [el; a]; a]];
|
|
||||||
T - apply[car [el; evlis [cdr [el; a]; a]]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
pairlis and assoc have been previously defined.
|
|
||||||
|
|
||||||
```
|
|
||||||
evcon[c; a] = [eval[caar [c]; a] -- eval[cadar [c]; a];
|
|
||||||
T -- evcon[cdr [c];a]]
|
|
||||||
and
|
and
|
||||||
|
|
||||||
|
```mexpr
|
||||||
|
evlis[m; a] = [null[m] -> NIL;
|
||||||
|
T -> cons [eval[car [m];a];evlis[cdr [m];a]]]
|
||||||
```
|
```
|
||||||
|
|
||||||
###### evlis[m;a] = [null[m] - NIL
|
<a name="page14">page 14</a>
|
||||||
|
|
||||||
##### T - cons [eval[car [m];a];evlis[cdr [m];a]]]
|
|
||||||
|
|
||||||
We shall explain a number of points about these definitions.
|
We shall explain a number of points about these definitions.
|
||||||
The first argument for - apply is a function. If it is an atomic symbol, then there
|
|
||||||
are two possibilities. One is that it is an elementary function: car, cdr, cons, eq,
|
|
||||||
or atom. In each case, the appropriate function is applied to the argument(s). If it is
|
|
||||||
not one of these, then its meaning has to be looked up in the association list.
|
|
||||||
If it begins with LAMBDA, then the arguments are paired with the bound variables,
|
|
||||||
and the form is given to -1 to evaluate.
|
|
||||||
If it begins with LABEL, then the function name and definition are added to the as-
|
|
||||||
sociation list, and the inside function is evaluated by apply.
|
|
||||||
The first argument of is a form. If it is atomic, then it must be a variable,
|
|
||||||
and its value is looked up on the association list.
|
|
||||||
If =of the form is QUOTE, then it is a constant, and the value is cadr of the form
|
|
||||||
itself.
|
|
||||||
If car of the form is CGND, then it is a conditional expression, and evcon evaluates
|
|
||||||
the propositional terms in order, and choses the form following the first true predicate.
|
|
||||||
In all other cases, the form must be a function followed by its arguments. The ar-
|
|
||||||
guments are then evaluated, and the function is given to apply.
|
|
||||||
The LISP Programming System has many added features that have not been de-
|
|
||||||
scribed thus far. These will be treated hereafter. At this point, it is worth noting the
|
|
||||||
following points.
|
|
||||||
|
|
||||||
1. In the pure theory of LISP, all functions other than the five basic ones need to
|
The first argument for `apply` is a function. If it is an atomic symbol, then there are two possibilities. One is that it is an elementary function: `car`, `cdr`, `cons`, `eq`, or `atom`. In each case, the appropriate function is applied to the argument(s). If it is not one of these, then its meaning has to be looked up in the association list.
|
||||||
be defined each time they are to be used. This is unworkable in a practical sense.
|
|
||||||
The LISP programming system has a larger stock of built-in functions known to the in-
|
If it begins with `LAMBDA`, then the arguments are paired with the bound variables, and the form is given to `eval` to evaluate.
|
||||||
terpreter, and provision for adding as many more as the programmer cares to define.
|
|
||||||
2. The basic functions car. and cdr were said to be undefined for atomic arguments.
|
If it begins with `LABEL`, then the function name and definition are added to the as-
|
||||||
In the system, they always have a value, although it may not always be meaningful.
|
sociation list, and the inside function is evaluated by apply.
|
||||||
Similarly, the basic predicate eq - always has a value. The effects of these functions
|
|
||||||
|
The first argument of `eval` is a form. If it is atomic, then it must be a variable, and its value is looked up on the association list.
|
||||||
|
|
||||||
|
If `car` of the form is `QUOTE`, then it is a constant, and the value is `cadr` of the form
|
||||||
|
itself.
|
||||||
|
|
||||||
|
If `car` of the form is `COND`, then it is a conditional expression, and `evcon` evaluates
|
||||||
|
the propositional terms in order, and choses the form following the first true predicate.
|
||||||
|
|
||||||
|
In all other cases, the form must be a function followed by its arguments. The arguments are then evaluated, and the function is given to apply.
|
||||||
|
|
||||||
|
The LISP Programming System has many added features that have not been described thus far. These will be treated hereafter. At this point, it is worth noting the following points.
|
||||||
|
|
||||||
|
1. In the pure theory of LISP, all functions other than the five basic ones need to be defined each time they are to be used. This is unworkable in a practical sense. The LISP programming system has a larger stock of built-in functions known to the interpreter, and provision for adding as many more as the programmer cares to define.
|
||||||
|
2. The basic functions `car` and `cdr` were said to be undefined for atomic arguments. In the system, they always have a value, although it may not always be meaningful.
|
||||||
|
Similarly, the basic predicate `eq` always has a value. The effects of these functions
|
||||||
in unusual cases will be understood after reading the chapter on list structures in the
|
in unusual cases will be understood after reading the chapter on list structures in the
|
||||||
computer.
|
computer.
|
||||||
3. Except for very unusual cases, one never writes (QUOTE T) or (QUOTE F),
|
3. Except for very unusual cases, one never writes `(QUOTE T)` or `(QUOTE F)`,
|
||||||
but T, and F respectively.
|
but T, and F respectively.
|
||||||
4. There is provision in LISP for computing with fixed and floating point numbers.
|
4. There is provision in LISP for computing with fixed and floating point numbers. These are introduced as psuedo-atomic symbols.
|
||||||
These are introduced as psuedo-atomic symbols.
|
|
||||||
The reader is warned that the definitions of apply and ~l given above are pedagogi-
|
|
||||||
cal devices and are not the same functions as those built into the LISP programming
|
|
||||||
system. Appendix B contains the computer implemented version of these functions and
|
|
||||||
should be used to decide questions about how things really work.
|
|
||||||
|
|
||||||
11. THE LISP INTERPRETER SYSTEM
|
The reader is warned that the definitions of `apply` and `eval` given above are pedagogical devices and are not the same functions as those built into the LISP programming system. Appendix B contains the computer implemented version of these functions and should be used to decide questions about how things really work.
|
||||||
|
|
||||||
The following example is a LISP program that defines three functions union, inter-
|
<a name="page15">page 15</a>
|
||||||
section, and member, and then applies these functions to some test cases. The functions
|
|
||||||
union and intersection are to be applied to "sets," each set being represented by a list
|
## II. THE LISP INTERPRETER SYSTEM
|
||||||
of atomic symbols. The functions are defined as follows. Note that they are all recur-
|
|
||||||
sive, and both union and intersection make use of member.
|
The following example is a LISP program that defines three functions `union`, `intersection`, and `member`, and then applies these functions to some test cases. The functions `union` and `intersection` are to be applied to "sets," each set being represented by a list of atomic symbols. The functions are defined as follows. Note that they are all recursive, and both union and intersection make use of member.
|
||||||
|
|
||||||
```
|
```
|
||||||
member[a;x] = [null[x]-~;e~[a;car[x]]-T;T-
|
member[a; x] = [null[x] -> F; eq[a; car[x]] -> T;
|
||||||
member [a;cdr [x]]]
|
T -> member[a; cdr[x]]]
|
||||||
union[^;^] = [null[x]-.y;member[car[x];y]-union
|
|
||||||
[cdr [x];~]; T-cons [c ar [x];union[c dr [x];~]]]
|
union[x; y] = [null[x] -> y;
|
||||||
|
member[car[x];y] -> union[cdr[x]; y];
|
||||||
|
T -> cons[car[x]; union[cdr[x]; y]]]
|
||||||
|
|
||||||
|
intersection[x;y] = [null[x] -> NIL;
|
||||||
|
member[car[x]; y] -> cons[car[x]; intersection[cdr[x]; y]];
|
||||||
|
T -> intersection[cdr[x]; y]]
|
||||||
```
|
```
|
||||||
|
|
||||||
To define these functions, we use the pseudo-function define. The program looks like
|
To define these functions, we use the pseudo-function define. The program looks like
|
||||||
|
@ -2712,47 +2736,45 @@ cator is found, and NIL otherwise.
|
||||||
This pseudo-function is used to create a constant by putting the indicator APVAL
|
This pseudo-function is used to create a constant by putting the indicator APVAL
|
||||||
and a value on the property list of an atomic symbol. The first argument should be an
|
and a value on the property list of an atomic symbol. The first argument should be an
|
||||||
atomic symbol; the second argument is the value is cons[val;N1~].
|
atomic symbol; the second argument is the value is cons[val;N1~].
|
||||||
```
|
|
||||||
|
|
||||||
csetq[ob;val] - FEXPR pseudo-function
|
#### csetq[ob; val] : FEXPR pseudo-function
|
||||||
|
|
||||||
|
csetq is like cset - except that it quotes its first argument instead of evaluating it.
|
||||||
|
|
||||||
|
#### remprop[x; ind] : SUBR pseudo-function
|
||||||
|
|
||||||
* csetq is like cset - except that it quotes its first argument instead of evaluating it.
|
|
||||||
rempr op[x; ind] : SUBR pseudo-function f
|
|
||||||
The pseudo-function remprop searches the list, x, looking for all occurrences of the
|
The pseudo-function remprop searches the list, x, looking for all occurrences of the
|
||||||
indicator ind. When such an indicator is found, its name and the succeeding property
|
indicator ind. When such an indicator is found, its name and the succeeding property
|
||||||
are removed from the list. The two "endsn of the list are tied together as indicated by
|
are removed from the list. The two "endsn of the list are tied together as indicated by
|
||||||
the dashed line below.
|
the dashed line below.
|
||||||
|
|
||||||
```
|
|
||||||
The value of remprop is NIL.
|
The value of remprop is NIL.
|
||||||
|
|
||||||
When an indicator appears on a property list without a property following it, then
|
When an indicator appears on a property list without a property following it, then
|
||||||
it is called a flag. An example of a flag is the indicator TRACE which informs the inter-
|
it is called a flag. An example of a flag is the indicator TRACE which informs the inter-
|
||||||
preter that the function on whose property list it appears is to be traced. There are two
|
preter that the function on whose property list it appears is to be traced. There are two
|
||||||
pseudo-functions for creating and removing flags respectively.
|
pseudo-functions for creating and removing flags respectively.
|
||||||
```
|
|
||||||
|
|
||||||
- flag [I; ind] EXPR pseudo-function
|
#### flag [I; ind] : EXPR pseudo-function
|
||||||
|
|
||||||
```
|
|
||||||
The pseudo-function flag puts the flag ind on the property list of every atomic symbol
|
The pseudo-function flag puts the flag ind on the property list of every atomic symbol
|
||||||
in the list 1. Note that d cannot be an atomic symbol, and must be a list of atomic sym-
|
in the list 1. Note that d cannot be an atomic symbol, and must be a list of atomic sym-
|
||||||
bols. The flag is always placed immediately following the first word of the property
|
bols. The flag is always placed immediately following the first word of the property
|
||||||
list, and the rest of the property list then follows. The value of flag is NIL. No property
|
list, and the rest of the property list then follows. The value of flag is NIL. No property
|
||||||
list ever receives a duplicated flag.
|
list ever receives a duplicated flag.
|
||||||
remflag[l; ind] : EXPR pseudo-function
|
|
||||||
|
#### remflag[l; ind] : EXPR pseudo-function
|
||||||
|
|
||||||
remflag removes all occurrences of the indicator ind from the property list of each
|
remflag removes all occurrences of the indicator ind from the property list of each
|
||||||
atomic symbol in the list 8. It does this by patching around the indicator with a rplacd
|
atomic symbol in the list 8. It does this by patching around the indicator with a rplacd
|
||||||
in a manner similar to the way remprop works.
|
in a manner similar to the way remprop works.
|
||||||
```
|
|
||||||
|
|
||||||
```
|
### Table Building and Table Reference Functions
|
||||||
Table Buildinrr and Table Reference Functions
|
|
||||||
```
|
#### pair [x; y] : SUBR
|
||||||
|
|
||||||
|
The function pair has as value the list of pairs of corresponding elements of the lists x and y. The arguments x and y must be lists of the same number of elements. They should & be atomic symbols. The value is a dotted pair list, i. e. ((a (a p2)...
|
||||||
|
|
||||||
- pair [x; y] SUBR
|
|
||||||
The function pair has as value the list of pairs of corresponding elements of the lists
|
|
||||||
x and y. The arguments x and y must be lists of the same number of elements. They
|
|
||||||
should & be atomic symbols. The value is a dotted pair list, i. e. ((a (a p2)...
|
|
||||||
pair[x;y] = [prog[u;v; m]
|
pair[x;y] = [prog[u;v; m]
|
||||||
u:= x;
|
u:= x;
|
||||||
v:= y;
|
v:= y;
|
||||||
|
@ -2765,7 +2787,10 @@ m:= cons[cons[car[u];car[v]];m];
|
||||||
u:= cdr[u];
|
u:= cdr[u];
|
||||||
v:= cdr[v];
|
v:= cdr[v];
|
||||||
go[~Il
|
go[~Il
|
||||||
sassoc[x;y;u] SUBR functional
|
```
|
||||||
|
|
||||||
|
#### sassoc[x; y; u] : SUBR functional
|
||||||
|
|
||||||
The function sassoc searches y, which is a list of dotted pairs, for a pair whose first
|
The function sassoc searches y, which is a list of dotted pairs, for a pair whose first
|
||||||
element that is x. If such a pair is found, the value of sassoc is this pair. Otherwise
|
element that is x. If such a pair is found, the value of sassoc is this pair. Otherwise
|
||||||
the function u of no arguments is taken as the value of sassoc.
|
the function u of no arguments is taken as the value of sassoc.
|
||||||
|
@ -2781,12 +2806,12 @@ the S-expression y in the S-expression z.
|
||||||
|
|
||||||
T .- cons[subst[x;y;car [z]];subst [x;y;cdr[e]]]]
|
T .- cons[subst[x;y;car [z]];subst [x;y;cdr[e]]]]
|
||||||
|
|
||||||
* sublis [x ; y] SUBR
|
#### sublis [x ; y] : SUBR
|
||||||
|
|
||||||
Here x is a list of pairs,
|
Here x is a list of pairs,
|
||||||
((ul vl) (u2 v2) (un vn))
|
((u<sub>1</sub> . v<sub>1</sub>) (u<sub>2</sub> . v<sub>2</sub>) (u<sub>n</sub> . v<sub>n</sub>))
|
||||||
The value of sublis[x;y] is the result of substituting each v for the corresponding
|
The value of `sublis[x; y]` is the result of substituting each `v` for the corresponding
|
||||||
u in y.
|
`u` in `y`.
|
||||||
Note that the following M-expression is different from that given in Section I, though
|
Note that the following M-expression is different from that given in Section I, though
|
||||||
the result is the same.
|
the result is the same.
|
||||||
|
|
||||||
|
@ -2819,38 +2844,33 @@ nconc does not copy its first argument.
|
||||||
* conc concatenates its arguments without copying them. Thus it changes existing list
|
* conc concatenates its arguments without copying them. Thus it changes existing list
|
||||||
structure and is a pseudo-function. The value of conc is the resulting concatenated list.
|
structure and is a pseudo-function. The value of conc is the resulting concatenated list.
|
||||||
|
|
||||||
nc - onc [x;y] SUBR pseudo-function
|
#### nconc [x; y] : SUBR pseudo-function
|
||||||
|
|
||||||
```
|
The function `nconc` concatenates its arguments without copying the first one. The
|
||||||
The function nconc concatenates its arguments without copying the first one. The
|
|
||||||
operation is identical to that of attrib except that the value is the entire result, (i. e. the
|
operation is identical to that of attrib except that the value is the entire result, (i. e. the
|
||||||
modified first argument, x).
|
modified first argument, x).
|
||||||
|
|
||||||
The program for nconc[x;y] has the program variable m and is as follows:
|
The program for nconc[x;y] has the program variable m and is as follows:
|
||||||
|
```
|
||||||
nconc [x; y ] = prog [[m];
|
nconc [x; y ] = prog [[m];
|
||||||
|
[null[x] - return[~]]
|
||||||
```
|
```
|
||||||
|
|
||||||
##### [null[x] - ret~rn[~]]
|
#### COPY [X] : SUBR
|
||||||
|
|
||||||
* COPY [XI SUBR
|
|
||||||
|
|
||||||
```
|
|
||||||
This function makes a copy of the list x. The value of copy is the location of the
|
This function makes a copy of the list x. The value of copy is the location of the
|
||||||
copied list.
|
copied list.
|
||||||
```
|
|
||||||
|
|
||||||
##### copy[x] = [null[x] - ~~~;atom[x] - x;T -- cons[copy[car[x]]
|
copy[x] = [null[x] - ~~~;atom[x] - x;T -- cons[copy[car[x]]
|
||||||
|
|
||||||
```
|
```
|
||||||
co~[cdr[xllIl
|
co~[cdr[xllIl
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
#### reverse[t] : SUBR
|
||||||
reverseit] SUBR
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
This is a function to reverse the top level of a list. Thus
|
This is a function to reverse the top level of a list. Thus
|
||||||
reverse[(^ B (C. D))] = ((C D) B A))
|
reverse[(A B (C. D))] = ((C D) B A))
|
||||||
reverse[t] = prog[[v];
|
reverse[t] = prog[[v];
|
||||||
u: =t;
|
u: =t;
|
||||||
```
|
```
|
||||||
|
|
|
@ -147,4 +147,11 @@
|
||||||
((ATOM Z) Z)
|
((ATOM Z) Z)
|
||||||
((QUOTE T) (CONS (SUBST X Y (CAR Z)) (SUBST X Y (CDR Z))))))
|
((QUOTE T) (CONS (SUBST X Y (CAR Z)) (SUBST X Y (CDR Z))))))
|
||||||
(SYSIN)
|
(SYSIN)
|
||||||
(SYSOUT) (TERPRI) (TIMES) (TRACE) (UNTRACE) (ZEROP LAMBDA (N) (EQ N 0)))
|
(SYSOUT) (TERPRI) (TIMES) (TRACE)
|
||||||
|
(UNION LAMBDA (X Y)
|
||||||
|
(COND
|
||||||
|
((NULL X) Y)
|
||||||
|
((MEMBER (CAR X) Y) (UNION (CDR X) Y))
|
||||||
|
(T (CONS (CAR X) (UNION (CDR X) Y)))))
|
||||||
|
(UNTRACE)
|
||||||
|
(ZEROP LAMBDA (N) (EQ N 0)))
|
||||||
|
|
|
@ -164,17 +164,32 @@
|
||||||
(number? value)
|
(number? value)
|
||||||
(symbol? value)
|
(symbol? value)
|
||||||
(= value NIL))
|
(= value NIL))
|
||||||
(do
|
(try
|
||||||
(.rplaca cell value)
|
(.rplaca cell value)
|
||||||
cell)
|
cell
|
||||||
|
(catch Throwable any
|
||||||
|
(throw (ex-info
|
||||||
|
(str (.getMessage any) " in RPLACA: `")
|
||||||
|
{:cause :upstream-error
|
||||||
|
:phase :host
|
||||||
|
:function :rplaca
|
||||||
|
:args (list cell value)
|
||||||
|
:type :beowulf}
|
||||||
|
any))))
|
||||||
(throw (ex-info
|
(throw (ex-info
|
||||||
(str "Invalid value in RPLACA: `" value "` (" (type value) ")")
|
(str "Invalid value in RPLACA: `" value "` (" (type value) ")")
|
||||||
{:cause :bad-value
|
{:cause :bad-value
|
||||||
:detail :rplaca})))
|
:phase :host
|
||||||
|
:function :rplaca
|
||||||
|
:args (list cell value)
|
||||||
|
:type :beowulf})))
|
||||||
(throw (ex-info
|
(throw (ex-info
|
||||||
(str "Invalid cell in RPLACA: `" cell "` (" (type cell) ")")
|
(str "Invalid cell in RPLACA: `" cell "` (" (type cell) ")")
|
||||||
{:cause :bad-value
|
{:cause :bad-cell
|
||||||
:detail :rplaca}))))
|
:phase :host
|
||||||
|
:function :rplaca
|
||||||
|
:args (list cell value)
|
||||||
|
:type :beowulf}))))
|
||||||
|
|
||||||
(defn RPLACD
|
(defn RPLACD
|
||||||
"Replace the CDR pointer of this `cell` with this `value`. Dangerous, should
|
"Replace the CDR pointer of this `cell` with this `value`. Dangerous, should
|
||||||
|
@ -189,17 +204,32 @@
|
||||||
(number? value)
|
(number? value)
|
||||||
(symbol? value)
|
(symbol? value)
|
||||||
(= value NIL))
|
(= value NIL))
|
||||||
(do
|
(try
|
||||||
(.rplacd cell value)
|
(.rplacd cell value)
|
||||||
cell)
|
cell
|
||||||
|
(catch Throwable any
|
||||||
|
(throw (ex-info
|
||||||
|
(str (.getMessage any) " in RPLACD: `")
|
||||||
|
{:cause :upstream-error
|
||||||
|
:phase :host
|
||||||
|
:function :rplacd
|
||||||
|
:args (list cell value)
|
||||||
|
:type :beowulf}
|
||||||
|
any))))
|
||||||
(throw (ex-info
|
(throw (ex-info
|
||||||
(str "Invalid value in RPLACD: `" value "` (" (type value) ")")
|
(str "Invalid value in RPLACD: `" value "` (" (type value) ")")
|
||||||
{:cause :bad-value
|
{:cause :bad-value
|
||||||
:detail :rplaca})))
|
:phase :host
|
||||||
|
:function :rplacd
|
||||||
|
:args (list cell value)
|
||||||
|
:type :beowulf})))
|
||||||
(throw (ex-info
|
(throw (ex-info
|
||||||
(str "Invalid cell in RPLACD: `" cell "` (" (type cell) ")")
|
(str "Invalid cell in RPLACD: `" cell "` (" (type cell) ")")
|
||||||
{:cause :bad-value
|
{:cause :bad-cell
|
||||||
:detail :rplaca}))));; PLUS
|
:phase :host
|
||||||
|
:detail :rplacd
|
||||||
|
:args (list cell value)
|
||||||
|
:type :beowulf}))));; PLUS
|
||||||
|
|
||||||
(defn LIST
|
(defn LIST
|
||||||
[& args]
|
[& args]
|
||||||
|
@ -394,38 +424,54 @@
|
||||||
(make-beowulf-list (map CAR @oblist))
|
(make-beowulf-list (map CAR @oblist))
|
||||||
NIL))
|
NIL))
|
||||||
|
|
||||||
|
(defn PUT
|
||||||
|
"Put this `value` as the value of the property indicated by this `indicator`
|
||||||
|
of this `symbol`. Return `value` on success.
|
||||||
|
|
||||||
|
NOTE THAT there is no `PUT` defined in the manual, but it would have been
|
||||||
|
easy to have defined it so I don't think this fully counts as an extension."
|
||||||
|
[symbol indicator value]
|
||||||
|
(let [magic-marker (Integer/parseInt "777778" 8)]
|
||||||
|
(if-let [binding (ASSOC symbol @oblist)]
|
||||||
|
(if-let [prop (ASSOC indicator (CDDR binding))]
|
||||||
|
(RPLACD prop value)
|
||||||
|
(RPLACD binding
|
||||||
|
(make-cons-cell
|
||||||
|
magic-marker
|
||||||
|
(make-cons-cell
|
||||||
|
indicator
|
||||||
|
(make-cons-cell value (CDDR binding))))))
|
||||||
|
(swap!
|
||||||
|
oblist
|
||||||
|
(fn [ob s p v]
|
||||||
|
(make-cons-cell
|
||||||
|
(make-beowulf-list (list s magic-marker p v))
|
||||||
|
ob))
|
||||||
|
symbol indicator value))))
|
||||||
|
|
||||||
|
(defn DEFLIST
|
||||||
|
"For each pair in this association list `a-list`, set the property with this
|
||||||
|
`indicator` of the symbol which is the first element of the pair to the
|
||||||
|
value which is the second element of the pair."
|
||||||
|
[a-list indicator]
|
||||||
|
(map
|
||||||
|
#(PUT (CAR %) indicator (CDR %))
|
||||||
|
a-list))
|
||||||
|
|
||||||
(defn DEFINE
|
(defn DEFINE
|
||||||
"Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten
|
"Bootstrap-only version of `DEFINE` which, post boostrap, can be overwritten
|
||||||
in LISP.
|
in LISP.
|
||||||
|
|
||||||
The single argument to `DEFINE` should be an assoc list which should be
|
The single argument to `DEFINE` should be an association list of symbols to
|
||||||
nconc'ed onto the front of the oblist. Broadly,
|
lambda functions"
|
||||||
(SETQ OBLIST (NCONC ARG1 OBLIST))"
|
[a-list]
|
||||||
[args]
|
(DEFLIST a-list 'EXPR))
|
||||||
(swap!
|
|
||||||
oblist
|
|
||||||
(fn [ob arg1]
|
|
||||||
(loop [cursor arg1 a arg1]
|
|
||||||
(if (= (CDR cursor) NIL)
|
|
||||||
(do
|
|
||||||
(.rplacd cursor @oblist)
|
|
||||||
(pretty-print a)
|
|
||||||
a)
|
|
||||||
(recur (CDR cursor) a))))
|
|
||||||
(CAR args)))
|
|
||||||
|
|
||||||
(defn SET
|
(defn SET
|
||||||
"Implementation of SET in Clojure. Add to the `oblist` a binding of the
|
"Implementation of SET in Clojure. Add to the `oblist` a binding of the
|
||||||
value of `var` to the value of `val`. NOTE WELL: this is not SETQ!"
|
value of `var` to the value of `val`. NOTE WELL: this is not SETQ!"
|
||||||
[symbol val]
|
[symbol val]
|
||||||
(when
|
(PUT symbol 'APVAL val))
|
||||||
(swap!
|
|
||||||
oblist
|
|
||||||
(fn [ob s v] (if-let [binding (ASSOC symbol ob)]
|
|
||||||
(RPLACD binding v)
|
|
||||||
(make-cons-cell (make-cons-cell s v) ob)))
|
|
||||||
symbol val)
|
|
||||||
val))
|
|
||||||
|
|
||||||
;;;; TRACE and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;; TRACE and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@
|
||||||
cond := lsqb (opt-space cond-clause semi-colon opt-space)* cond-clause rsqb;
|
cond := lsqb (opt-space cond-clause semi-colon opt-space)* cond-clause rsqb;
|
||||||
cond-clause := mexpr opt-space arrow opt-space mexpr opt-space;
|
cond-clause := mexpr opt-space arrow opt-space mexpr opt-space;
|
||||||
arrow := '->';
|
arrow := '->';
|
||||||
args := mexpr | (opt-space mexpr semi-colon opt-space)* opt-space mexpr opt-space;
|
args := arg | (opt-space arg semi-colon opt-space)* opt-space arg opt-space;
|
||||||
|
arg := mexpr | sexpr;
|
||||||
fn-name := mvar;
|
fn-name := mvar;
|
||||||
mvar := #'[a-z][a-z0-9]*';
|
mvar := #'[a-z][a-z0-9]*';
|
||||||
mconst := #'[A-Z][A-Z0-9]*';
|
mconst := #'[A-Z][A-Z0-9]*';
|
||||||
|
|
Loading…
Reference in a new issue