3

Consider this macro helper function that returns a backquote expression:

(defun make-headers ()
  `(:headers `(("Authorization" . ,(get-auth)))))

This returns the list (:headers `(("Authorization" . ,(get-auth)))), suitable for interpolating into a macro expansion.

Now I want to add an argument which, if not nil, will be used as-is as an additional header; if nil, the original list should be returned. I can't figure out how to interpolate down multiple backquote levels. I thought multiple commas might work, like:

(defun make-headers (content-type)
  `(:headers `(("Authorization" . ,(get-auth))
               ,,@(when content-type (list (cons "Content-Type" content-type))))))

...but this doesn't work as I expected. The best I can do is to awkwardly sort-of duplicate what the original internal backquote was doing:

(defun make-headers (content-type)
  `(:headers (append (list (cons "Authorization" (get-auth)))
                     ,(when content-type (list 'list (list 'cons "Content-Type" content-type)))))))

That's pretty terrible, though. Isn't there a simpler way to interpolate down multiple backquote levels?

For an example simpler than the above, consider this:

(let ((z :z)) `(:foo :bar `(:x :y ,z)))

This evaluates to

(:foo :bar `(:x :y ,z))

So how about:

(let ((z :z)) `(:foo :bar `(:x :y ,,z)))

That produces:

(:foo :bar `(:x :y ,:z))

How can I produce just:

(:foo :bar `(:x :y :z))
Sean
  • 929
  • 4
  • 13

1 Answers1

2

This is maybe as good as it gets:

(let ((z :z)) `(:foo :bar (backquote (:x :y ,z))))

That gives you this:

(:foo :bar (backquote (:x :y :z)))

But maybe someone has a better suggestion. I have a feeling that Elisp doesn't quite have what it takes in this regard. Other Lisp dialects might work better for this.

Drew
  • 75,699
  • 9
  • 109
  • 225