将对象参数传递给宏

时间:2014-01-07 20:28:47

标签: multithreading macros lisp common-lisp ccl

将对象参数传递给宏时遇到错误。我必须引用这个论点,把它放在一个列表中,还是不引用它?

我希望使用Clozure Common Lisp使用读写锁来并行生成和运行多个进程,以控制数据输出到另一个进程。 with-write-lock是一个宏,等待给定的锁可用于写访问,然后在保持锁的情况下执行其主体。但是,无论我如何尝试将锁传递给with-write-lock,我都会收到错误。我想我遇到了麻烦,因为我无法理解如何将锁定对象传递给with-write-lock宏。如果我将锁绑定到符号,我会得到解构错误:

(let ((l (make-read-write-lock)))
  (with-write-lock l (1+ 1)))
==>
> Error: L can't be destructured against the lambda list (LOCK), because it is not a proper list.
  

在执行Listener(4)的过程中执行:(:INTERNAL CCL :: NX1-COMPILE-LAMBDA)。

但是如果我将调用make-read-write-lock作为带锁定参数传递给with-write-lock,那么我得到一个未声明的自由变量错误:

(with-write-lock (make-read-write-lock) (1+ 1))
==>
;Compiler warnings for "/Users/frank/Documents/Lisp/threaded/act-parallel.lisp" :
;In an anonymous lambda form at position 18: Undeclared free variable MAKE-READ-WRITE-LOCK
  

错误:未绑定变量:MAKE-READ-WRITE-LOCK   执行时:#,在进程Listener(4)中执行。

我失败了,因为我误解了如何将一个对象传递给一个宏,或者我是否会出错,因为或者更具体的写入锁定?

这是Clozure Common Lisp(macros.lisp)附带的with-write-lock宏:

(defmacro with-write-lock ((lock) &body body)
  (let* ((locked (gensym))
         (p (gensym)))
    `(with-lock-context
       (let* ((,locked (make-lock-acquisition))
              (,p ,lock))
         (declare (dynamic-extent ,locked))
         (unwind-protect
              (progn
                (write-lock-rwlock ,p ,locked)
                ,@body)
           (when (lock-acquisition.status ,locked) (unlock-rwlock ,p)))))))

1 个答案:

答案 0 :(得分:3)

该宏的lambda列表正在解构其参数。

 ((lock) &body body)

意味着它希望第一个参数作为包含锁定然后是正文形式的列表。这是CL中非常标准的宏参数列表,您可以像这样使用它:

(with-write-lock (lock)
  ..... body forms ....)

所以你的例子就是

(let ((l (make-read-write-lock)))
   (with-write-lock (l) (1+ 1)))

(with-write-lock ((make-read-write-lock)) (1+ 1))

分别。注意第一个参数周围的额外数据。 对于类似的宏,请参阅with-open-filedestructuring-bind

(with-open-file ("path/to/file" :open :args)
  .... body ...)

(destructuring-bind (one two three) '(1 2 3)
  .... body forms ...)