4

Q: How can I test (programmatically) whether a variable has been defined, but not initialized?

(defvar foo)

EXAMPLE:

(if (my-test foo)
  (message "%s has been defined, but not initialized." foo)
  (message "%s has been defined AND initialized." foo))
lawlist
  • 18,826
  • 5
  • 37
  • 118
  • 1
    The problem is that, at the lowest level of LISP, just mentioning a variable (technically an atom in LISP) makes it exist. To ask the question of whether it exists, you have to mention it, so the answer is always Yes. The `defvar` _does_ do a bit more that just make the variable exist, but I'm not sure any of that would be good enough. If you don't care about that distinction, you could use `boundp` which just tests if there's a value. – MAP Jan 18 '17 at 18:27

1 Answers1

6

The following works only with lexical binding, because with dynamic binding (defvar foo) has no real effect. It checks whether let-binding the variable affects the dynamic value or not. I used the term "declared" instead of "defined", because (defvar foo) doesn't quite feel like a full definition to me (e.g., it only applies to the file it's in) so it's more like C's "declare".

;; -*- lexical-binding: t -*-

(defvar foo 2)
(defvar bar)

(defmacro check-var (var)
  `(message "%s %s"
            ',var
            (cond ((boundp ',var) "has been initialized")
                  ((let ((,var t)) (boundp ',var))
                   "has been declared, but not initialized")
                  (t "has NOT been declared nor initialized"))))

(check-var foo)
(check-var bar)
(check-var qux)
npostavs
  • 9,033
  • 1
  • 21
  • 53