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.
str
. What is it? Where is it defined? Can you show howpcre/match-lambda-form
is called? – Filumstr
is a symbol that has been defined by an enclosingLET
and represents a variable name that is safe to use. – Phylacterypcre/match-lambda-form
is called like so:(pcre/match-lambda-form '("foo"))
, where the"foo"
has been read by a stream reader processing strings of the form#~m/foo/
. – Phylacterydefmacro!
from chapter 3, which usesdefmacro/g!
, which uses... (you get the idea) :) – Phylactery(equal ``(,,a) '(list 42))
gives NIL to me when tried in the SBCL REPL. I too would like to understand this kind of macros. I've still not started with them, though. – Moltke