7

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
  • 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, 2017 at 16:18

3 Answers 3

6

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.
2
  • 1
    Great to know!!! You could describe the difference between the usage of setq-default compared to defconst? Oct 3, 2017 at 21:26
  • 2
    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, 2017 at 23:38
7

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.

8
  • Where do I put my documentation ?
    – politza
    Sep 6, 2017 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. Sep 6, 2017 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. Sep 10, 2017 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. Sep 10, 2017 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. Sep 10, 2017 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 and acknowledge you have read our privacy policy.

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