;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*-

=Node: Cells and Locatives

=Text:
3CELLS AND LOCATIVES*

     A 1locative* is a type of Lisp object used as a 1pointer* to a 1cell*.  Locatives are inherently a more
low level construct than most Lisp objects; they require some knowledge of the nature of the Lisp
implementation.

     A 1cell* is a machine word that can hold a (pointer to a) Lisp object.  For example, a symbol has
five cells:  the print name cell, the value cell, the function cell, the property list cell, and the package
cell.  The value cell holds (a pointer to) the binding of the symbol, and so on.  Also, an array leader
of length 1n* has 1n* cells, and an 2art-q* array of 1n* elements has 1n* cells.  (Numeric arrays do not have
cells in this sense.) A locative is an object that points to a cell; it lets you refer to a cell so that
you can examine or alter its contents.

3contents* 1locative*                                                                                               
        Returns the contents of the cell which the locative points to.  This is actually the same as
        2cdr*, for reasons explained below, but it is clearer to use 2contents* when the argument is
        normally a locative.

        To modify the contents of the cell, use 2setf* on 2contents*:  

                3(setf (contents loc) newvalue)*

     The macro 2locf* (see 4(EVAL-2)locf*) can be used to convert a form that accesses a cell to
one that creates a locative pointer to that cell:  for example, 

        3(locf (fsymeval x))*

     evaluates to a locative that points to the function cell of the value of 2x*; that is to say, it points
to the place where 2(fsymeval x)* is stored.

     2locf* is very convenient because it saves the writer and reader of a program from having to
remember the names of many functions that would create locatives to cells found in different
fashions.

     One thing you should know is that it is not possible to make a locative to an element of a
numeric array.  For example, 

        3(setq foo (make-array 10 :type art-1b))*
        3(locf (aref foo 0))*

     signals an error.  Locatives may only point at entire words of memory, which contain standard
Lisp data.

     Because of cdr-coding (see 4(MANLISTSTR-1)Cdr-Coding*), a cons does not always contain an
explicit cell which points to its cdr.  Therefore, it is impossible to obtain a locative which points to
such a cell.  However, this is such a useful thing to do that 1the cons itself* is usually treated as if it
were a locative pointing to a cell which holds the cons's cdr.  2(locf (cdr x))* returns the value of 2x*,
and 2(contents x)* returns the cdr when 1x* is a cons, so 2(contents (locf (cdr x)))* is the same as 2(cdr
x)*, as it should be.  Most functions that are normally given locatives also accept a cons and treat it
as if it were a magic locative to the (nonexistent) cell containing the cdr of the cons.

     A cons always does contain a cell which points to the car, and 2(locf (car x))* returns a locative
whose pointer field is the same as that of 2x*'s value.

=Node: Functions That Operate on Locatives

=Text:
3FUNCTIONS THAT OPERATE ON LOCATIVES

location-boundp* 1locative*                                                                                    
        Returns 2t* if the cell to which 1locative* points contains anything except a void marker.

        The void marker is a special data type, 2dtp-null*, which is stored in cells to say that their
        value is missing.  For example, an unbound variable actually has a void marker in its value cell,
        and 2(location-boundp (locf x))* is equivalent to 2(variable-boundp x)*.  

3location-makunbound* 1locative* &optional 1pointer*                                                          
        Stores a void marker into the cell to which 1locative* points.  This consists of data type field
        2dtp-null* and a pointer copied from 1pointer*.

        The pointer field of the void marker is used to tell the error handler what variable was
        unbound.  In the case of a symbol's value cell or function cell, it should point to the symbol
        header.  In the case of a flavor method, it should point to the beginning of the block of data
        that holds the definition, which is a word containing the method's function spec.

        If the second arg is not specified, then where the void marker points is not defined.  

     Other functions with which locatives are expected or useful include 2get* (the locative points to
the cell in which the plist is stored), 2store-conditional* (the locative points to the cell to be tested and
modified), and 2%bind* (the locative points to the cell to be bound).

=Node: Mixing Locatives with Lists

=Text:
3MIXING LOCATIVES WITH LISTS*

     Either of the functions 2car* and 2cdr* (see 4(MANLISTSTR-1)Conses*) may be given a locative, and
will return the contents of the cell at which the locative points.  They are both equivalent to 2contents*
when the argument is a locative.

     Similarly, either of the functions 2rplaca* and 2rplacd* may be used to store an object into the cell
at which a locative points.  

For example,
        3(rplaca locative y)*
or
        3(rplaca locative y)*
is the same as
        3(setf (contents locative) y)*

     If you are just using locatives, you should use 2contents* rather than 2car* or 2cdr*.  But you can
also mix locatives and conses.  For example, the same variable may usefully sometimes have a
locative as its value and sometimes a cons.  Then it is useful that 2car* and 2cdr* work on locatives,
and it also matters which one you use.  Pick the one that is right for the case of a cons.

     For example, the following function conses up a list in the forward order by adding onto the end.
It needs to know where to put the pointer to the next cell.  Usually it goes in the previous cell's cdr,
but the first cell gets put in the cell where the list is supposed to end up.  A locative is used as the
pointer to this cell.  The first time through the loop, the 2rplacd* is equivalent to 2(setq res ...)*; on later
times through the loop the 2rplacd* tacks an additional cons onto the end of the list.  

        3(defun simplified-version-of-mapcar (fcn lst)*
        3  (do ((lst lst (cdr lst))*
        3       (res nil)*
        3       (loc (locf res)))*
        3      ((null lst) res)*
        3    (setf (cdr loc)*
        3          (setq loc (ncons (funcall fcn (car lst)))))))*

     2cdr* is used here rather than 2contents* because the normal case is that the argument is a list.  

