emacs-devel
[Top][All Lists]
Advanced

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

Re: void variable


From: Luc Teirlinck
Subject: Re: void variable
Date: Sun, 25 Jul 2004 15:46:15 -0500 (CDT)

Lars Hansen wrote:

   I now see that the docstring of defvar clearly says that the variable is 
     set only if it is void. So

      (let ((foo 'y)) (defvar foo 'x))

   should leave foo void as it does.

It has nothing to do with the fact that defvar only sets the variable
if void.  You get the same result with:
(let ((foo 'y)) (makunbound 'foo) (defvar foo 'x))
See the ielm run at the end of this posting.

What it has to do with is the following quote from
`(elisp)Defining Variables':

       *Warning:* If the `defconst' and `defvar' special forms are
    used while the variable has a local binding (made with `let', or a
    function argument), they set the local-binding's value; the
    top-level binding is not changed.  This is not what you usually
    want.  To prevent it, use these special forms at top level in a
    file, where normally no local binding is in effect, and make sure
    to load the file before making a local binding for the variable.

This also applies to defcustom.

   So there is no problem :-)

Unless other people might be confused by this too.  Maybe it might be
good to add the above warning to the involved docstrings.

What about the following patches?

===File ~/eval.c-diff=======================================
*** eval.c      19 Jul 2004 07:02:32 -0500      1.220
--- eval.c      25 Jul 2004 15:19:42 -0500      
***************
*** 742,747 ****
--- 742,754 ----
   This means that M-x set-variable recognizes it.
   See also `user-variable-p'.
  If INITVALUE is missing, SYMBOL's value is not set.
+ 
+ If SYMBOL has a local binding, then this form affects the local
+ binding.  This is usually not what you want.  Thus, if you need to
+ load a file defining variables, with this form or with `defconst' or
+ `defcustom', you should always load that file _outside_ any bindings
+ for these variables.  \(`defconst' and `defcustom' behave similarly in
+ this respect.)
  usage: (defvar SYMBOL &optional INITVALUE DOCSTRING)  */)
       (args)
       Lisp_Object args;
***************
*** 784,789 ****
--- 791,800 ----
  If SYMBOL is buffer-local, its default value is what is set;
   buffer-local values are not affected.
  DOCSTRING is optional.
+ 
+ If SYMBOL has a local binding, then this form sets the local binding's
+ value.  However, you should normally not make local bindings for
+ variables defined with this form.
  usage: (defconst SYMBOL INITVALUE [DOCSTRING])  */)
       (args)
       Lisp_Object args;
============================================================

===File ~/custom.el-diff====================================
*** custom.el   05 Jun 2004 22:41:36 -0500      1.75
--- custom.el   25 Jul 2004 15:19:30 -0500      
***************
*** 246,251 ****
--- 246,258 ----
        Specifies that SYMBOL should be set after the list of variables
          VARIABLES when both have been customized.
  
+ If SYMBOL has a local binding, then this form affects the local
+ binding.  This is normally not what you want.  Thus, if you need
+ to load a file defining variables with this form, or with
+ `defvar' or `defconst', you should always load that file
+ _outside_ any bindings for these variables.  \(`defvar' and
+ `defconst' behave similarly in this respect.)
+ 
  Read the section about customization in the Emacs Lisp manual for more
  information."
    ;; It is better not to use backquote in this file,
============================================================

Just to illustrate:

===File ~/foo-ielm==========================================
*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (let ((foo 1)) (defvar foo 2) foo)
1
ELISP> (boundp 'foo)
nil
ELISP> (let ((foo 1)) (makunbound 'foo) (defvar foo 2) foo)
2
ELISP> (boundp 'foo)
nil
ELISP> (let ((foo 1)) (defconst foo 2) foo)
2
ELISP> (boundp 'foo)
nil
ELISP> (defvar foo 3)
foo
ELISP> (let ((foo 1)) (makunbound 'foo) (defvar foo 2) foo)
2
ELISP> foo
3
ELISP> (makunbound 'foo)
foo
ELISP> (let ((foo 1)) (makunbound 'foo) (defcustom foo 2 "blabla") foo)
2
ELISP> (boundp 'foo)
nil
ELISP> (defcustom foo 3 "blabla")
foo
ELISP> (let ((foo 1)) (makunbound 'foo) (defcustom foo 2 "blabla") foo)
2
ELISP> foo
3
ELISP> 
============================================================




reply via email to

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