1

I want to use a macro to define variables. However, evaluating the macro does not define these vars. I seem to be missing something, but I can't find it. Here's the code:

(defmacro delve--build-cmp (name desc sort-fn-asc sort-fn-desc slot-fn &optional map-fn)
  "Define two comperator functions based on NAME."
  (declare (indent 1))
  (let* ((name-as-string (format "%s" name))
         (name-asc  (make-symbol (concat name-as-string "-asc")))
         (name-desc (make-symbol (concat name-as-string "-desc")))
         (desc-asc  (concat desc ", ascending order."))
         (desc-desc (concat desc ", descending order.")))
    `(progn
       (defvar ,name-asc
         (delve-cmp--create :comp (delve--cmp-fn ,sort-fn-asc ,slot-fn ,map-fn)
                            :desc ,desc-asc)
         ,desc-asc)
       (defvar ,name-desc
         (delve-cmp--create :comp (delve--cmp-fn ,sort-fn-desc ,slot-fn ,map-fn)
                            :desc ,desc-desc)
         ,desc-desc))))

The function delve-cmp--create is a function which defines a structure object, so nothing special there. All I want is to define these two objects at the time of the evaluation of the macro. I thought about using functions, but I like it that we can use unevaluated symbol names in macros which spares us the need to quote the name. In the end, I would like to have some kind of defun-like syntax.

So my question is: What is wrong with this code, why isn't the defvar eval'ed when I eval a call to that macro?

Drew
  • 75,699
  • 9
  • 109
  • 225

1 Answers1

3

The defvars are evaluated -- your uninterned symbols will have the values you've assigned.

Change make-symbol to intern.

phils
  • 48,657
  • 3
  • 76
  • 115
  • It work's! To be honest, I don't understand that "intern" thing; I thought that macros will be passed "as is", so the value for name will then be interned by `defvar`. I looked at the info page (elisp), but I guess I will read it again. Thanks anyways, it was the answer (and btw the answer to another macro question I had checked before, and I thought: nay, interning is not my problem....) – Public Image Ltd. Nov 26 '21 at 18:46
  • @PublicImageLtd. `make-symbol` is like a constructor. It makes a *new* thing. So `(make-symbol 'a)` creates a new symbol (whose name happens to be `a`) which is not equal to the thing you get when you write `'a`. It's like how there can be two people called Bruce, but they're clearly different people even though they have the same name. – Silvio Mayolo Nov 26 '21 at 23:55
  • @PublicImageLtd. You are potentially getting tripped up by the difference between the `read` and `eval` stages of execution. Consider that when you have `(defvar foo "value")` in your code, the lisp *reader* interns the symbol `foo` (and the symbol `defvar`) and when the code is subsequently *evaluated* it's the canonical/interned symbol `foo` which is being defined as a variable. Your macro was returning code for evaluation in which the symbol being defined as a variable was not the canonical/interned symbol of the name in question. – phils Nov 27 '21 at 01:59
  • ...and to emphasise further: the lisp reader (which reads text and converts it to lisp objects) reads your macro definition, and it reads the code calling your macro, but the lisp reader doesn't process the return value of your macro -- *that* is evaluated directly. Your macro isn't returning code in textual form, but lisp objects (which were either read previously in the macro and macro-call definitions, or generated during the macro expansion). – phils Nov 27 '21 at 02:08
  • If that's still confusing, do spend time researching/reading about the read and eval distinction until you feel you have a handle on them -- it will make a big difference to your understanding of lisp. – phils Nov 27 '21 at 02:12
  • "Your macro isn't returning code in textual form, but lisp objects" -- that's the source of my confusion! That's the same problem as the one pointed out by @Silvio Mayolo. I'd always assumed that `'a` is the same as `make-symbol "a"`. I'll dig into that a bit deeper, thanks. – Public Image Ltd. Nov 28 '21 at 09:07