REDUCE

4.4 Value Cell Functions

The contents of the value cell of an id is usually accessed by eval (Chapter 11) or valuecell (below) and changed by setq, setf or sometimes set.

(setq [VARIABLE:id VALUE:any]): any fexpr
The value of each VARIABLE is set to the corresponding value of VALUE. Each argument VALUE is evaluated, each argument VARIABLE is not evaluated. It is not true that
    (setq variable value)

is equivalent to

    (set 'variable value)

Where setq may be used to set any type of variable (fluid, global or local) the function set is restricted to fluid and global variables.

(set EXP:id VALUE:any): any expr
Set is used to define the value cell of fluid and global identifiers. An error occurs if EXP does not evaluate to an identifier.
    ⋆⋆⋆⋆⋆ An attempt was made to do SET on ‘EXP', which  is  not  
    an identifier

If EXP evaluates to t or nil an error occurs.

    ⋆⋆⋆⋆⋆ Cannot change T or NIL

(desetq U:any V:any): V:any macro
This function is part of the USEFUL package. Desetq is a destructuring setq. That is, the first argument is a list whose elements are ids. The value of each id is set to the corresponding element in the second argument. For example, evaluation of
    (desetq (A (B) . C) '((1) (2) (3) 4))

defines the value of A to be (1), B to be 2, and C to ((3) 4).

(psetq [VARIABLE:id VALUE:any]): Undefined macro
This function is defined in the USEFUL package. Psetq is very similar to setq. The difference is that with psetq each VALUE is evaluated before any assignment is made.
    1 lisp> (setq a 'same  b a)  
    SAME  
    2 lisp> (eq a b)  
    T  
    3 lisp> (psetq a 'other  b a)  
    OTHER  
    4 lisp> (eq a b)  
    NIL

(setf [LHS:form RHS:any]): RHS:any macro
The ability to assign values to ids allows us to think of ids as variables. We can generalize this notion of variable. For example, a list can be thought of as a collection of anonymous variables. Usually there are seperate access and update functions for each kind of generalized variable. For example the function cdr accesses the cdr of a pair, the function rplacd updates it. However, we can think of a call on an access function as a reference to a storage location. Just as we consider the mention of an id to be a reference to its value, (cdr pair) can be thought of as the name for the cdr for some pair. Rather than having to remember two functions for each kind of generalized variable (rplacd corresponds to cdr), we can adopt a uniform syntax for updating storage locations using the setf macro.

The application of setf can take on any one of the following forms:

(setf id data) expands into (setq id data)

(setf (eval form) data) expands into (set form data)

The same effect is obtained by substituting value in place of eval.

(setf (car pair) data) expands into (rplaca pair data)

(setf (cdr pair) data) expands into (rplacd pair data)

(setf (getv vector index) data) expands into
(putv vector index data)

(setf (indx form index) data) expands into
(setindx form index data)

(setf (sub form start size) data) expands into
(setsub form start size data)

(setf (nth pair index) data) expands into an expression similar to
(rplaca (pnth pair index) data)

If the first argument to setf is a macro then it will be expanded before setf is. For example, if first is defined as

(ds first (p) (car p)) then

(setf (first p) data) is equivalent to (setf (car p) data)

The USEFUL module contains an expanded version of setf. The basic definition of setf is not consistent with that of setq. The value returned from an application of setq is always the value assigned. For example, the expression

(setf (car '(a b)) 'd) expands into (rplaca '(a b) 'd)

The value returned after evaluating this second expression is (d b). The extended version of setf will always return the value assigned.

An application of the extended version of setf will accept the additional following forms:

(setf (cons left right) pair) will expand into an expression similar to
(progn (setf left (car pair)) (setf right (cdr pair)))

(setf (cXYr pair) data) expands into an expression similar to
(rplacX (cYr pair) data)

where X is either a or d and Y is either a, d, aa, ..., or ddd

(setf (flagp id name) data) expands into an expression similar to
(flag (list id) name), if data is non-nil otherwise
(remflag (list id) name)

(setf (get id name) data) expands into (put id name data)

(setf (getd name) data) expands into an expression similar to
(putd name (car data) (cdr data))

This expansion assumes that data is similar to an expression which would be returned by a call on getd. If data is a code-pointer or a lambda expression then ’expr is used in place of (car data).

(setf (lastcar pair) data) expands into an expression similar to
(rplaca (lastpair pair) data).

(setf (list a b c ...) pair)
the expansion of this expression is very similar to the expansion of
(desetq (a b c ...) pair)

(setf (pnth pair index) data) expands into an expression similar to
(rplacd (pnth pair (sub1 index)) data)

(setf (vector al bl cl ...) [ar br cr ...])
expands into an expression similar to
(progn (setf al ar)(setf bl br)(setf cl cr)...)

The setf function is extensible to permit additional operators on the left hand side. If there is an assign-op property on the property list of the operator then the value of that property (either a lambda expression or the name of a function) is used to build the expansion of the macro. The effect is similar to

    (apply (get op 'assign-op) (append (cdr lhs) (list rhs)))

The property setf-expand is searched for when their is no assign-op property. If there is such a property its value is applied to the two arguments passed to setf. The effect is similar to

    (apply op (list lhs rhs))

If the left hand side operator is flagged as setf-safe, then it is assumed that the expansion of the macro will yeild an expression which will return the value of the right hand side. Otherwise the expansion will take one of the forms listed below. Within the second expansion, references to RHS are replaced with references to VAR. The second form is used when RHS is a list, the assumption being that it is effecient to evaluate an application only once.

    (progn expansion rhs)  
 
    (let ((var rhs))  
      expansion  
      var)

(psetf [LHS:form RHS:any]): Undefined macro
This function is defined in the USEFUL package. Psetf is very similar to setf. The difference is that with psetf each RHS is evaluated before any assignment is made.

(makeunbound U:id): Undefined expr
U is made an unbound identifier, that is to say it will no longer have a value. This function should be applied to fluid identifiers only.

(valuecell U:id): any expr
Safe access to the value cell of an id. If U is not an id a type mismatch error occurs. If U is an unbound id, an unbound id error occurs. Otherwise the current value of U is returned. This function should be applied to fluid identifiers only.

(unboundp U:id): boolean expr
Returns t is U is unbound. This function should be applied to fluid identifiers only.