lambda - 在定义宏的方法中处理 lambda 列表

标签 lambda macros common-lisp

例如,我想从 lambda 列表中获取所有变量来定义宏:

(defmacro my-defun (name lambda-list &body body &aux (fname (gensym)))
  `(progn
     (defun ,fname ,(all-vars lambda-list)
       ,@body)
     (defun ,name ,lambda-list
       (,fname ,@(all-vars lambda-list)))))

是否有一些函数可以使用 lambda 列表来完成此操作或其他事情,或者是否没有比编写这样的函数更简单的方法:

(defun all-vars (lambda-list)
  (mapcar (lambda (cons) (if (consp cons) (car cons) cons))
          (remove-if (lambda (symbol) (and (symbolp symbol)
                                           (char= (char (symbol-name symbol) 0) #\&)))
                     lambda-list)))

最佳答案

这种方法您必须做的事情,或者需要找到一个已经实现它的库。有一些库可以处理 lambda 列表解析(每个实现都必须这样做,至少在内部)。通常不会太难,只是乏味。

也就是说,您的 all-vars 实现不太正确。 ordinary lambda lists 中关键字参数的完整规范是:

[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]] 

这意味着您可以,例如,

(defun (&key ((:long-keyword-name x) "EX" xp))
  ...)

当你执行(if (consp cons) (car cons) cons)时,你会得到(:long-keyword-name x),而不是<强>x。

这是一个我认为有效的版本,但尚未经过广泛测试:

(defun lambda-list-variables (lambda-list)
  "Returns, in order, the variables declared in an ordinary lambda list,
but doesn't check that the lambda-list is actually legal."
  (labels ((ll-keyword-p (x)
             (member x lambda-list-keywords))
           (to-var (x)
             (if (symbolp x)
                 x             ; required, optional, rest, key, and aux 
                 (destructuring-bind (var &rest init-and-supplied) x
                   (declare (ignore init-and-supplied))
                   (if (listp var)
                       (second var)     ; key vars
                       var)))))         ; optional, key, and aux vars
    (remove-if #'ll-keyword-p
               (mapcar #'to-var lambda-list))))

CL-USER> (lambda-list-variables
          '(a b 
            &optional c (d 'dee) (e 'ee e-p)
            &rest f
            &key
            g
            (h 'aitch)
            (i 'eye i-p)
            ((:jay j))
            ((:kay k) 'kay)            
            ((:ell l) 'ell l-p)
            &aux 
            m
            (n 'en)))
;=> (A B C D E F G H I J K L M N)

关于lambda - 在定义宏的方法中处理 lambda 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29411770/

相关文章:

Lambda 包括对 node_modules 的依赖

lisp - 比较 Lisp 中的列表

javascript - Parenscript 和隐式 Return

java - 多行 lambda 比较器

java - 如何使用lambda在构造函数参数中实现 > 1 接口(interface)方法?

java - 实例方法引用。没有找到合适的方法

lisp - 条件照应收集最佳实践?

macros - Clojure 科尔马 : Cannot run an aggregate count

macros - 没有打开的图像 - Fiji/ImageJ 宏语言

c++ - MSVC 内置宏 _M_AMD64 和 _M_X64 之间的区别