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, 2018 at 11:58

1 Answer 1


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, 2018 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, 2018 at 13:10
  • yes @phils is right, just as setq auto-quotes the variable argument, this macro does the same. Aug 21, 2018 at 15:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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