[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: when should a variable to quoted?
From: |
sunway |
Subject: |
Re: when should a variable to quoted? |
Date: |
Sat, 13 Sep 2008 04:06:31 -0700 (PDT) |
User-agent: |
G2/1.0 |
"elisp lacks of lexical variable", if this happens to the C
programming language:
int a=10;
foo(a);
may be "a" will be changed to 9 ?
if so, I really hate this feature....
On Sep 13, 5:38 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
> sunway <sunwayfore...@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.