all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: pjb@informatimago.com (Pascal J. Bourguignon)
To: help-gnu-emacs@gnu.org
Subject: Re: when should a variable to quoted?
Date: Sat, 13 Sep 2008 11:38:18 +0200	[thread overview]
Message-ID: <87k5dg9yid.fsf@hubble.informatimago.com> (raw)
In-Reply-To: 5bdb1b73-bf04-49a3-8629-61d32ef6f899@p31g2000prf.googlegroups.com

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	other threads:[~2008-09-13  9:38 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-13  9:11 when should a variable to quoted? sunway
2008-09-13  9:38 ` Pascal J. Bourguignon [this message]
2008-09-13 10:21   ` Eli Zaretskii
2008-09-13 11:06   ` sunway
2008-09-13 12:29     ` Pascal J. Bourguignon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k5dg9yid.fsf@hubble.informatimago.com \
    --to=pjb@informatimago.com \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.