首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在定义宏的方法中处理lambda列表

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

Stack Overflow用户
提问于 2015-04-02 19:26:04
回答 2查看 134关注 0票数 2

例如,我想从lambda-list中获取所有变量来定义一个宏:

代码语言:javascript
复制
(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-list可以更容易地处理其他事情,或者没有比编写这样的函数更容易的方法:

代码语言:javascript
复制
(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)))
EN

回答 2

Stack Overflow用户

发布于 2015-04-02 19:51:21

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

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

代码语言:javascript
复制
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]] 

这意味着你可以,例如,

代码语言:javascript
复制
(defun (&key ((:long-keyword-name x) "EX" xp))
  ...)

当你执行(if (consp cons) (car cons) cons)时,你会得到(:-keyword-name x)返回,而不是x

这是一个我认为可以工作的版本,但没有进行广泛的测试:

代码语言:javascript
复制
(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))))

代码语言:javascript
复制
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)
票数 2
EN

Stack Overflow用户

发布于 2015-04-04 21:08:32

很多次我写了这样的函数,结果发现它已经在alexandria库中了。

代码语言:javascript
复制
(ql:quickload :alexandria)

然后

代码语言:javascript
复制
CL-USER> (alexandria:parse-ordinary-lambda-list '(a b c &optional x &key (ham 1 used-ham)))

返回

代码语言:javascript
复制
(A B C)
((X NIL NIL))
NIL
(((:HAM HAM) 1 USED-HAM))
NIL
NIL 
T
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29411770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档