从“兰帕达书”一书中,“a1”在sortf中的位置是什么?

时间:2018-01-20 20:36:58

标签: macros common-lisp sorting-network let-over-lambda

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

1 个答案:

答案 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))