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?

3

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

Change make-symbol to intern.

6
  • 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....) 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. 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 1: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 2: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 2:12

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.