I'm reading Let Over Lambda, which deals with some pretty deeply layered macro authoring. It's fascinating and I'm mostly managing to keep up with it.
In Chapter 4 Hoyte implements reader macros for CL-PPCRE match and replace functions, such that you can do things like:
(#~m/(foo|bar)\d+/ "Some foo99") ; matches!
(#~s/foo(\d+)/bar\1/, "Some foo99") ; "Some bar99
In order to achieve this, we define a macro that uses the double-backquote, since it is actually expanded by a wrapper macro, which needs the quoted value (it returns a lambda form). Within the quasi-quoted list, there is some use of the following sequence ,',varname
, which I can't get my head around. What does the initial ,'
do here?
(defmacro! pcre/match-lambda-form (o!args)
"Expands to a lambda that applies CL-PPCRE:SCAN"
``(lambda (,',g!str)
(cl-ppcre:scan ,(car ,g!args)
,',g!str)))
Actually, it's probably better that I distill that down to something that uses just defmacro
, for clarity if you haven't read the book. str
is a symbol and args
is a list:
(defmacro pcre/match-lambda-form (args)
"Expands to a lambda that applies CL-PPCRE:SCAN"
``(lambda (,',str)
(cl-ppcre:scan ,(car ,args)
,',str)))
Are the quotes basically double-quoting the inner parts, so that the result can be unquoted twice? Effectively putting 'str
into the expanded form, instead of just str
?
EDIT | Thanks to Terje D. and some playing around in the REPL, this is pretty much the situation:
(defvar a 42)
(equal ``(,,a) '(list 42)) ; T
(equal ``(,a) '(list a)) ; T
(equal ``(,',a) ''(42)) ; T
(equal ``(a) ''(a)) ; T (obviously)
So:
- Doubly-unquoted, form is fully expanded.
- Singly-unquoted, form is not expanded.
- Unquoted with a comma, form is fully expanded and the result quoted.