I found this snippet of code from oremacs

(defmacro csetq (variable value)
  `(funcall (or (get ',variable 'custom-set) 'set-default) ',variable ,value))

I would like to expand this macro so that is can take multiple pairs of arguments similar to setq (e.g. (csetq foo 'bar fod 'baz str "a") etc). I made an initial attempt, but it always returns nil and leaves me with a lot of nested progn forms when expanded.

(defmacro csetq (variable value &rest rest)
  (when variable
      `(progn (funcall (or (get ',variable 'custom-set) 'set-default) ',variable ,value)
              (csetq ,(car rest) ,(cadr rest) ,(cddr rest)))))

Is there a way to fix this macro so that it returns the last value set (similar to setqand does not nest?

  • It returns nil because this is the terminating condition for your recursion, i.e. when will evaluate to nil when you exhausted the list of rest. You can change the terminating condition to be a test for single last element instead. – wvxvw Aug 21 '18 at 11:58

There are many options, but here's one approach:

(defmacro csetq (&rest pairs)
  "For each SYMBOL VALUE pair, calls either `custom-set' or `set-default'."
  (let (forms)
    (while pairs
      (let ((variable (pop pairs))
            (value (pop pairs)))
        (push `(funcall (or (get ',variable 'custom-set) 'set-default)
                        ',variable ,value)
    `(progn ,@(nreverse forms))))
  • While for illustration purposes this is OK, in principle, this requires storing the value of evaluation of ,variable and reusing it. It may be an expression, not necessarily a symbol, in which case you may get inconsistent results. – wvxvw Aug 21 '18 at 12:01
  • It's a good point, but I don't think it's an issue here in practice. I believe the intention was that it would always be a symbol; and in any case (get ',variable 'custom-set) necessitates that the value of variable is a symbol, no? – phils Aug 21 '18 at 13:10
  • yes @phils is right, just as setq auto-quotes the variable argument, this macro does the same. – Prgrm.celeritas Aug 21 '18 at 15:14

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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