help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: when should a variable to quoted?


From: Pascal J. Bourguignon
Subject: Re: when should a variable to quoted?
Date: Sat, 13 Sep 2008 11:38:18 +0200
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/22.2 (gnu/linux)

sunway <sunwayforever@gmail.com> writes:

> (add-to-list 'll "a")
> (delete-dups ll)
>
> The variable "ll" needs be quoted in add-to-list, while not quoted in
> delete-dups, why? any special reasons?

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.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]