Each symbol has associated with it a value cell , which refers to one Lisp object. This object is called the symbol's binding or value , since it is what you get when you evaluate the symbol. The binding of symbols to values allows symbols to be used as the implementation of variables in programs. The value cell can also be empty , referring to no Lisp object, in which case the symbol is said to be unbound . This is the initial state of a symbol when it is created. An attempt to evaluate an unbound symbol causes an error. The binding of a symbol can be changed either by lambda-binding or by assignment . The difference is that when a symbol is lambda-bound, its previous value is saved away, to be restored later, whereas assignment discards the previous value. The symbols nil and t are always bound to themselves; they may not be assigned nor lambda-bound. (The error of changing the value of t or nil is not yet detected, but it will be.) When closures are in use, the situation is a little more complicated. See the section on closures. When a Lisp function is compiled , most of its variables are compiled into local variables , which are not represented by means of symbols. However the compiler recognizes usage of the setq special form, and of the set and value-cell-location functions with a quoted argument, as referring to variables rather than symbols, and generates the appropriate code to access the corresponding local variable rather than the symbol.
(declare (special foo)) (or (boundp 'foo) (setq foo 'bar))
Example: (set (cond ((eq a b) 'c) (t 'd)) 'foo)will either set c to foo or set d to foo .
Example: (setq x (+ 3 2 1) y (cons x nil))x is set to 6 , y is set to (6) , and the setq returns (6) . Note that the first assignment was performed before the second form was evaluated, allowing that form to use the new value of x .
Example: (setq a 1) (setq b 2) (psetq a b b a) a => 2 b => 1
Example: (setq a 1) a => 1 (makunbound 'a) a => causes an error.makunbound returns its argument.
Every symbol also has associated with it a function cell . The function cell is similar to the value cell; it refers to a Lisp object. When a function is referred to by name, that is, when a symbol is applied or appears as the car of a form to be evaluated, that symbol's function cell is used to find its definition , the functional object which is to be applied. For example, when evaluating (+ 5 6) , the evaluator looks in + 's function cell to find the definition of + , in this case a FEF containing a compiled program, to apply to 5 and 6. Maclisp does not have function cells; instead, it looks for special properties on the property list. This is one of the major incompatibilities between the two dialects. Like the value cell, a function cell can be empty, and it can be lambda-bound or assigned. The following functions are analogous to the value-cell related functions in the previous section.
The usual means of putting a function in a symbol's function cell (defining the symbol) is by means of the defun special form. Macros are put in a symbol's function cell by means of the macro special form. Substitutable functions can be put there with the defsubst special form. Anything else requires the deff special form.
(defun name type lambda-list body )The type is only for Maclisp compatibility, and is optional and usually absent. The lambda-list is as described on this link and may contain "&-keywords".
Examples: (defun addone (x) (1+ x)) (defun foo (a &optional (b 5) c &rest e &aux j) (setq j (+ a b)) (cond ((not (null c)) (cons j e)) (t j)))A list (named-lambda name lambda-list . body) is left in the function cell of name . For compatibility, the Maclisp type s expr , fexpr , and macro , and Maclisp lexprs (which have an atomic lambda-list) are recognized and the corresponding Lisp Machine flavor of defun is assumed.
(defsubst name lambda-list . body )and does almost the same thing. It defines a function which executes identically to the one which a similar call to defun would define. The difference comes when a function which calls this one is compiled. Then, the call will be open-coded by substituting the substitutable function's definition into the code being compiled. Substitutable functions are a sort of cross between ordinary functions and macros; they can be applied like functions, but act like macros for the compiler. The actual definition looks like (subst lambda-list . body) . For example, if we define
(defsubst square (x) (* x x)) (defun foo (a b) (square (+ a b)))then if foo is used interpreted, square will work just as if it had been defined by defun . If foo is compiled, however, the squaring will be substituted into it and it will compile just like
(defun foo (a b) (* (+ a b) (+ a b)))You will notice that the substitution performed is very simple and takes no care about the possibility of computing an argument twice when it really ought to be computed once.
(macro name (arg ) body )
Examples: (macro addone (x) (list '1+ (cadr x))) (macro increment (x) (list 'setq (cadr x) (list '1+ (cadr x))))In the function cell of name is placed a cons whose car is the symbol macro , and whose cdr is a lambda -expression of the form (lambda (arg) . body) . Much of the time it is more convenient and clear to use a macro-defining macro such as defmacro (see LINK:(defmacro-fun)) to define macros.
(deff name definition )where definition is evaluated so you can get any object you want. For example,
(deff foo 'bar)will make foo equivalent to bar , with an indirection so that if bar changes foo will likewise change;
(deff foo (function bar))copies the definition of bar into foo with no indirection, so that further changes to bar will have no effect on foo .
(def foo ;So the definition of foo can be found (local-declare ((arglist x y &rest z)) (defun foo (&rest rest-arg) .....)))literal-flag allows the caller of arglist to say that declared arglists of this sort should not be used. arglist cannot be relied upon to return the exactly correct answer, since some of the information may have been lost. Programs interested in how many and what kind of arguments there are should use args-info instead. arglist is a reliable way of getting the names of the arguments, if that information is available, provided the literal-flag argument is t . This inhibits use of arglist declarations.
%arg-desc-quoted-rest | ||
If this bit is set, the function has a "rest" argument, and it is "quoted". Most special forms have this bit. | ||
%arg-desc-evaled-rest | ||
If this bit is set, the function has a "rest" argument, and it is not "quoted". | ||
%arg-desc-fef-quote-hair | ||
If this bit is set, there are some quoted arguments other than the "rest" argument (if any), and the pattern of quoting is too complicated to describe here. The ADL (Argument Description List) in the FEF should be consulted. | ||
%arg-desc-interpreted | ||
This function is not a compiled-code object, and a numeric argument descriptor cannot be computed. Usually args-info will not return this bit, although %args-info will. | ||
%arg-desc-fef-bind-hair | ||
There is argument initialization, or something else too complicated to describe here. The ADL (Argument Description List) in the FEF should be consulted. | ||
%%arg-desc-min-args | ||
This is the minimum number of arguments which may be passed to this function, i.e., the number of "required" parameters. | ||
%%arg-desc-max-args | ||
This is the maximum number of arguments which may be passed to this function, i.e., the sum of the number of "required" parameters and the number of "optional" paramaters. If there is a rest argument, this is not really the maximum number of arguments which may be passed; an arbitrarily-large number of arguments is permitted, subject to limitations on the maximum size of a stack frame. |
Every symbol has associated with it a property list , which is a list used for associating "attributes" with symbols. A property list has an even number of elements. Each pair of elements constitutes a property ; the first of the pair is a symbol called the indicator , and the second is a Lisp object called the value or, more loosely, the property . The indicator serves as the name of the property, and the value as the value of the property. Here is an example of the property list of a symbol named b1 which is being used by a program which deals with blocks:
(color blue on b6 associated-with (b2 b3 b4))There are three properties, and so the list has six elements. The first property's indicator is the symbol color , and its value is the symbol blue . One says that "the value of b1 's color property is blue ", or, informally, that "b1 's color property is blue ." The program is probably representing the information that the block represented by b1 is blue. Similarly, it is probably representing in the rest of the property list that block b1 is on top of block b6 , and that b1 is associated with blocks b2 , b3 , and b4 . When a symbol is created, its property list is initially nil . Because of the existence of print-name, value, function, and package cells, none of the Maclisp system property names (expr , fexpr , macro , array , subr , lsubr , fsubr , and in former times value and pname ) exist in Lisp Machine lisp. The compiler (see this link) and the editor use several properties, which are documented in those sections.
It is also possible to have a "disembodied" property list, which is not associated with any symbol. A disembodied property list is a cons. Its car may be used for any purpose. The property list resides in its cdr. The way to create a disembodied property list is with (ncons nil) . In all of the functions in this section, disembodied property lists may be used as well as symbols; for brevity, the text speaks only of symbols.
Example: If the property list of foo is (baz 3) (get 'foo 'baz) => 3 (get 'foo 'zoo) => nil
Example: If the property list of foo were (bar (1 2 3) baz (3 2 1) color blue height six-two) then (getl 'foo '(baz height)) => (baz (3 2 1) color blue height six-two)
Example: (putprop 'Nixon 'not 'crook)If sym already has a property with the name indicator , then that property is removed first; this insures that getl will always find the property that was added most recently.
Example: (defprop foo bar next-to)is the same as
(putprop 'foo 'bar 'next-to)
Example: If the property list of foo was (color blue height six-three near-to bar) then (remprop 'foo 'height) => (six-three near-to bar) and foo's property list would be (color blue near-to bar)If sym has no indicator -property, then remprop has no side-effect and returns nil .
Every symbol has an associated string called the print-name , or pname for short. This string is used as the external representation of the symbol: if the string is typed in to read , it is read as a reference to that symbol (if it is interned), and if the symbol is print ed, print types out the print-name. For more information, see the section on the reader (see LINK:(reader)) and printer (see LINK:(printer)).
Examples: (samepnamep 'xyz (maknam '(x y z)) => t (samepnamep 'xyz (maknam '(w x y)) => nil (samepnamep 'xyz "xyz") => tThis is the same function as string-equal (see LINK:(string-equal-fun)).
Example: (get-pname 'xyz) => "xyz"
Normally, one wants to refer to the same symbol every time the same print-name-like string is typed. So, when read sees such a character-string in the input to Lisp, it looks in a table called the obarray for some symbol with that print-name. If it finds such a symbol, then that is what it returns; otherwise, it creates a symbol with that print-name (using the make-symbol function, see below), enters that symbol on the obarray, and returns it. The sub-function of read which performs these functions is called intern , and when a symbol has been entered on the obarray it is said to be interned . A symbol can also be uninterned , indicating that it is not on the obarray and cannot be referred to simply by typing its print name. Such symbols can be used as objects within a data-structure, but can cause trouble during debugging because they cannot be "typed in" directly, yet they look just like interned symbols when "typed out". Actually there can be many obarrays; the Lisp Machine system includes a feature called the package system (see LINK:(package)) which keeps track of multiple packages or name spaces and their interrelationships, using separate obarrays for each package.
Examples: (setq a (make-symbol "foo")) => foo (symeval a) => ERROR!Note that the symbol is not interned; it is simply created and returned.
Examples: if (gensym) => g0007 then (gensym 'foo) => f0008 (gensym 40) => f0032 (gensym) => f0033Note that the number is in decimal and always has four digits, and the prefix is always one character. gensym is usually used to create a symbol which should not normally be seen by the user, and whose print-name is unimportant, except to allow easy distinction by eye between two such symbols. The optional argument is rarely supplied. The name comes from "generate symbol", and the symbols produced by it are often called "gensyms".