prefix macro, similar to '?
Common Lisp macros typically use included-prefix notation: (operator stuff...)
However, the special quote macro ' uses concatenated-prefix notation: operator stuff , or alternatively operator(stuff).
I would like to create a custom macro in SBCL Common Lisp, let's call it !, that uses concatenation-prefix syntax to operate on a following list (or even atom), in a similar manner to ' . So I could invoke it anywhere, eg (setq foo !(bar) ), without it being infixed in parentheses itself.
How can this be done? What would the defmacro syntax look like? Thanks.
I see 2 ways to do it.
The first, simple variant is suitable, if you need it only for a single or very limited number of cases and you're satisfied with using just a single symbol as a prefix (like !
in the example case). You can create a read-macro, more specifically set a macro-character
to substitute such operator for, say, addition:
(set-macro-character #! (lambda (stream char)
(declare (ignore char))
(cons '+ (let ((next (read stream t nil t)))
(if (consp next) next
(list next)))))
CL-USER> !1
1
CL-USER> !(1 2)
3
The other, more complex and more flexible way is to define a macro, inside which apply a custom transformation, that will turn concatenated-prefix code into included-prefix. This trick uses the fact, that ordinary Lisp reader will read the in the same way both foo(bar)
and foo (bar)
, ie it will split them into 2 elements.
The simple version of such macro may look like this:
(defmacro with-prefix-syntax (&body body)
`(progn ,@(loop :for tail :on body :while body
:collect (if (and (not (atom (second tail)))
(fboundp (first tail)))
(prog1 (cons (first tail) (second tail)
(setf tail (rest tail)))
(first tail)))))
It will transform only top-level forms:
CL-USER> (macroexpand-1 '(with-prefix-syntax
print(1)))
(PROGN (PRINT 1))
CL-USER> (macroexpand-1 '(with-prefix-syntax
1))
(PROGN 1)
CL-USER> (macroexpand-1 '(with-prefix-syntax
print(1)
2))
(PROGN (PRINT 1) 2)
But not work in the lower levels:
CL-USER> (macroexpand-1 '(with-prefix-syntax
print(1)
(+ print(2))))
(PROGN (PRINT 1) (+ PRINT (2)))
Though it's rather easy to make it recursively transform all the layers (which is left as an exercise to the reader :)
链接地址: http://www.djcxy.com/p/52358.html上一篇: Vim:动态语法
下一篇: 前缀宏,类似于'?