Reputation: 23
I've been trying to make a macro for 'wrapping' functions, i.e. if I have a function that will take a list and cons the symbol 'a to the first element, it'd normally be defined as lambda (l) (cons 'a l), but I want a macro that will take a function and a list of integer-expression pairs and 'wrap' that function by making a new function that takes the some arguments of the old function and gets the rest based on the pairs, using the integer as a position and the expression as the value to give the function. Something like this:
(wrap list (0 'blah) (2 'bloo) (4 'blee))
Should expand to:
(lambda (a1 a2 . rest)
(apply list 'blah a1 'bloo a2 'blee rest))
Problem is, I don't know how to get the macro to find the value of the integer in the pair, it only knows it as a syntax object. I'm fairly new to macros and this should be fairly simple, I'm just having trouble with the docs, and I can't find any info on the web other than simple tutorials on macros. Any help would be appreciated.
Upvotes: 0
Views: 385
Reputation: 222973
This seems like a crazy macro to want to write, especially when SRFI 26 is so much more intuitive to use. Instead of (wrap list (0 'blah) (2 'bloo) (4 'blee))
, you can just use:
(cut list 'blah <> 'bloo <> 'blee <...>)
That is surely much easier to read.
If you really must write such a macro, here's one way to go about it, by transforming usages of wrap
into equivalent usages of cut
:
(require (for-syntax syntax/parse) srfi/26)
(define-syntax (wrap stx)
(syntax-parse stx
((_ func:expr (idx:nat expr:expr) ...)
(let* ((alist (map cons
(syntax->datum #'(idx ...))
(syntax-e #'(expr ...))))
(upper (add1 (apply max -1 (map car alist))))
(listfunc (lambda (i)
(cond ((assv i alist) => cdr)
(else #'<>)))))
(with-syntax (((args ...) (build-list upper listfunc)))
#'(cut func args ... <...>))))))
The key to answering your question, about how to get the integers given the syntax objects, is by using syntax->datum
(for deep syntax-stripping) or syntax-e
(for shallow syntax-stripping).
(P.S. (To Racket experts reading this.) I'm very new to syntax-parse
, so I'm sure syntax-parse
experts can find better ways to write the above. I originally wrote the macro as a syntax-case
macro, then slapped on syntax-parse
syntax classes. That's it.)
Upvotes: 3