前缀宏,类似于'?

Common Lisp宏通常使用包含前缀符号:(operator stuff ...)

但是,特殊引用宏'使用连接前缀符号:运算符的东西,或者运算符(东西)。

我想在SBCL Common Lisp中创建一个自定义宏,让我们称它为!,它使用级联前缀语法来操作后续列表(甚至原子),与''类似。 所以我可以在任何地方调用它,例如(setq foo!(bar)),而不会将它插入圆括号本身。

如何才能做到这一点? defmacro语法是什么样的? 谢谢。


我看到了两种方式来做到这一点。

第一个简单的变体是合适的,如果你只需要它用于单个或非常有限的情况,并且只使用单个符号作为前缀(例如在示例中为! )就满意了。 您可以创建一个读取宏,更具体地说,可以设置一个macro-character来代替这样的操作符,例如添加:

(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

另一种更复杂,更灵活的方式是定义一个宏,在其中应用自定义转换,将连接前缀代码转换为包含前缀。 这个技巧使用的事实是,普通的Lisp阅读器将以同样的方式读取foo(bar)foo (bar) ,即它将它们分成2个元素。

这种宏的简单版本可能如下所示:

(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)))))

它只会转变顶级形式:

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)

但在低层不行:

CL-USER> (macroexpand-1 '(with-prefix-syntax
                           print(1)
                           (+ print(2))))
(PROGN (PRINT 1) (+ PRINT (2)))

虽然使它递归地转换所有图层是相当容易的(这是作为练习留给读者的:)

链接地址: http://www.djcxy.com/p/52357.html

上一篇: prefix macro, similar to '?

下一篇: Syntax Highlighting tool/language that works with multiple editors