5

I know we have defvar and setq. defvar has a special meaning on defining global variables because the assignment only happens once. So I was thinking about use setq to get the desired behavior of defparameter from Common Lisp. However when I use setq without defvar (as replacement) I got a warning: reference to free-variable.

I saw on the table of hyperpolyglot lisp global-var section which relates defparameter with setq and set, so seems this is common. But I'm still wondering about the warnings...

There is another alternative to declare global variables as defparameter does? (declare and can change calling again)

  • 1
    It's not nearly as big of a problem in practice that defvar doesn't reset the variable when loading lisp code, you can C-M-x on the form to reset it manually. – wasamasa Sep 5 '17 at 16:18
4

In Emacs Lisp, defconst doesn't actually enforce constness, and therefore works pretty much like Common Lisp's defparameter:

  • it unconditionally sets the variable;
  • it marks it as special;
  • it avoids any warnings due to setting unbound variables.
  • Great to know!!! You could describe the difference between the usage of setq-default compared to defconst? – Manoel Vilela Oct 3 '17 at 21:26
  • 1
    If a variable is buffer-local, setq-default sets the default value, while setq and defconst set the local value. So they're completely different. Don't use setq-default unless you understand what it does. – jch Oct 3 '17 at 23:38
6

Not as far as I can tell, no.

I've always questioned the usefulness of having both defvar and defparameter in Common Lisp. If you don't mind, leave a comment explaining why having both forms is useful - I'm honestly interested to know. I know what they do, I just don't know why the difference is important enough for both forms to be in the standard.

Anyway, here's a macro that works for me:

(defmacro defparameter (var value &optional docstring)
  `(if (boundp ',var)
       (setq ,var ,value)
     (defvar ,var ,value ,docstring)))

That's my first defmacro, so feel free to offer improvements. I'm normally a scheme guy.

  • Where do I put my documentation ? – politza Sep 6 '17 at 11:17
  • Right after the parameter list, like a regular Emacs function. Try doing M-x find-function and finding the source for something like when or dolist for examples. – Jeff Spaulding Sep 6 '17 at 18:05
  • I was thinking... setq-default would not do exactly what I want? At least when I tested worked as I expected without warnings. – Manoel Vilela Sep 10 '17 at 8:06
  • About usefulness of both forms on Common Lisp, this is something I have my doubts too. defvar can avoid the problem of reload file or calling again of some function. Let say we want declare (defvar counter 0) inside of a function as similar of static of C, but is bad calling again as it because will erase our counter. defparameter, in another hand, ensure that the value is setted with dynamic-binding and resetted (if was declared previously). Actually, I always wondered why have so much ways to assign variables (setq, setf, setv, set, defvar, defparameter) in CL... but too late to ask. – Manoel Vilela Sep 10 '17 at 8:37
  • I like in general use defparameter instead defvar to declare global variables in CL. This avoid problems on development with emacs and the need to manually reset variables — is painful sometimes. Because if you are changing the code a lot, and you have really much code, the better way is just restart the REPL. But using defparameter you just re-eval the buffer. BTW, at least reading the code of community, defparameter is a common practice. I only see defvar used when that line of code have the intention to be executed again and we don't want to change the value when this happens in anyway. – Manoel Vilela Sep 10 '17 at 8:44
1

This version of defparameter in elisp tries to be a bit tighter - requiring the name to be a non-nil symbol, the documentation if present to be a string, and ensuring that the initial-value form is not evaluated more than once (in case it has side-effects).

(defmacro defparameter (name &optional initial-value documentation)
  "Like `cl-defvar', but unconditionally sets the named variable to the evaluation of the `initial-value' form."
  (assert (and name (symbolp name)) t "Name must be a non-nil symbol")
  (assert (or (not documentation) (stringp documentation)) t "Documentation if passed must be a string")
  (let ((value-sym (cl-gensym "value")))
    `(let ((,value-sym ,initial-value))
       (cond
         ((boundp ',name)
          (setq ,name ,value-sym)
          ,@(and documentation `((put ',name 'variable-documentation ,documentation)))
          ',name)
         (t
          (defvar ,name ,value-sym ,@(and documentation `(,documentation))))))))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.