>
> Lisp passes its arguments by-value.
>
> Therefore a function cannot modify the variables from which the values
> it gets come.
>
> It still can modify the value, when it is mutable, but not the variable.
>
> Usually, when we want to have a variable (or in general, a place)
> modified, we have to use a macro, or a special operator.
>
> (setq ll (list 1 2 3)) ; setq is a special operator.
> (require 'cl)
> (push 0 ll) Â Â Â Â Â Â ; push is a macro
>
> Otherwise, you must take care to get the result and store it back into
> the variable:
>
> (setq ll (delete ll 2)) ; delete modifies the value of ll, and returns
> Â Â Â Â Â Â Â Â Â Â Â Â ; the modified value, but when it's the first
> Â Â Â Â Â Â Â Â Â Â Â Â ; element that is deleted, we need to modify
> Â Â Â Â Â Â Â Â Â Â Â Â ; the variable too.
>
> For some reason (probably historical), emacs lisp authors prefer to
> use a function add-to-list instead of a macro push. Â Because there is
> no lexical variable in emacs lisp, but only special variables, where
> the value of the variable is always stored inside the symbol, in the
> symbol-value slot, we can consider any symbol to be a "pointer" to the
> variable. Therefore it is possible to pass a symbol to a function that
> will modify its symbol-value, thus modifying the variable named by
> this symbol. Â In lisp with lexical variables such as scheme or Common
> Lisp, it wouldn't work.
>
> In the case of delete-dups, it's like in the case of delete, but since
> it can never reduce to an empty list if passed an non empty list, it
> can modify the value in such a way that the variable always points to
> the right value. Â Namely, delete-dups modifies the first cons cell of
> the list it gets.
>
> Delete doesn't take this special step, so when you delete the first
> elements, the result returned and the value of the variable are not
> the same cons cell:
>
> (let ((list (list 1 1 2 2 3 3)))
> Â (print (delete 1 list))
> Â list)
> prints: Â (2 2 3 3)
> returns: (1 1 2 2 3 3)
>
> We could try to write delete so it modifies the first cons cell:
>
> (defun smart-delete (item list)
> Â Â (let* ((first-cell list)
> Â Â Â Â Â (head (cons nil list))
> Â Â Â Â Â (list head))
> Â Â Â (while (cdr list)
> Â Â Â Â (if (equal item (cadr list))
> Â Â Â Â Â (setf (cdr list) (cddr list))
> Â Â Â Â Â (setf list (cdr list))))
> Â Â Â (if (null (cdr head))
> Â Â Â Â Â nil
> Â Â Â Â Â (progn (setf (car first-cell) (cadr head)
> Â Â Â Â Â Â Â Â Â Â Â (cdr first-cell) (cddr head))
> Â Â Â Â Â Â Â Â first-cell))))
>
> (let ((list (list 1 1 2 2 1 3 3)))
> Â (print (smart-delete 1 list))
> Â list)
> prints: Â (2 2 3 3)
> returns: (2 2 3 3)
>
> But this wouldn't work when emptying the list:
> (let ((list (list 1 1 1)))
> Â (print (smart-delete 1 list))
> Â list)
> prints: Â nil
> returns: (1 1 1)
>
> because there is no way of modifying a cons cell to make it the symbol
> nil.
>
> --
> __Pascal Bourguignon__ Â Â Â Â Â Â Â Â Â Â
http://www.informatimago.com/
>
> ATTENTION: Despite any other listing of product contents found
> herein, the consumer is advised that, in actuality, this product
> consists of 99.9999999999%% empty space.