Doug Hoyte撰写的“Let over Lambda”一书通过sorting networks描述了固定大小输入的快速排序功能:
(defmacro! sortf (comperator &rest places)
(if places
`(tagbody
,@(mapcar
#`(let ((,g!a #1=,(nth (car a1) places))
(,g!b #2=,(nth (cadr a1) places)))
(if (,comperator ,g!b ,g!a)
(setf #1# ,g!b
#2# ,g!a)))
(build-batcher-sn (length places))))))
表达式'(car a1)'和'(cadr a1)'中的符号'a1'来自哪里?
顺便说一下。 'defmacro!'是一个定义宏的宏,它引入了'g!{symbol}'语法,通过'gensym'创建一个新的符号。 'build-batcher-sn'使用sorting network构建Batcher's algorithm。
答案 0 :(得分:2)
我发现这很奇怪,mapcar
只会接受一个功能而let
不符合条件。因此,必须有其他东西,令人惊讶的是,#`
是一个读者宏,它围绕下面的表达式创建一个函数:
'#`(list a b c)
; ==> (lambda (a1) `(list a b c))
注意我引用它,因为它是一个读取宏,它仍然会扩展,但结果会被引用。所以a1
来自读者宏。这是它的定义和激活:
(defun |#`-reader| (stream sub-char numarg)
(declare (ignore sub-char))
(unless numarg (setq numarg 1))
`(lambda ,(loop for i from 1 to numarg
collect (symb 'a i))
,(funcall
(get-macro-character #\`) stream nil)))
(set-dispatch-macro-character
#\# #\` #'|#`-reader|)
有问题的代码:
'#`(let ((,g!a #1=,(nth (car a1) places))
(,g!b #2=,(nth (cadr a1) places)))
(if (,comperator ,g!b ,g!a)
(setf #1# ,g!b
#2# ,g!a)))
; ==>
(lambda (a1)
`(let ((,g!a ,(nth (car a1) places))
(,g!b ,(nth (cadr a1) places)))
(if (,comperator ,g!b ,g!a)
(setf ,(nth (car a1) places) ,g!b ,(nth (cadr a1) places) ,g!a))))
要使用更多参数,请在前面添加数字:
'#2`(list ,a1 ,a2)
; ==> (lambda (a1 a2) `(list ,a1 ,a2))