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
  • 19,106
  • 5
  • 38
  • 120
  • 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,203
  • 1
  • 24
  • 53