Elisp递归宏

时间:2013-05-12 18:18:42

标签: macros lisp elisp

尝试在elisp中定义resursive宏

(defmacro remacro (keys)
  (if keys
      `(func1 ,(car keys)
            ,(remacro (cdr keys)))
      ))



(macroexpand '(remacro '(a b c)))

但它最终在

 Lisp nesting exceeds `max-lisp-eval-depth'

错误。

想要得到像

这样的结果
(func1 a (func1 b (func1 c nil nil) '(c)) '(b c))

(remacro '(a b c))

请告诉我如何纠正这个定义。

还有一件事我可以将`keys'定义为休息参数,如

(defmacro remacro (&rest keys)
  (if keys
      `(abc ,(car keys)
            ,(remacro `,@(cdr keys)))
      ))

尝试了这个,但它没有用。

使用案例:

基本上我想定义一个函数

设置以alist方式排列的树节点

(它仍然不起作用,必须继续工作)

(defmacro set-tree-node (tree e &rest keys)
  `(setcdr
    ,(if keys
         `(assoc (car keys)
                 (pushnew
                  (list ,(car keys))
                  (cdr
                   ,(set-tree-node `(cdr ,xtree) e `,@(cdr keys)))
                  :key 'car))
         tree)
    e))


(setq egtree nil)

运行后

(set-tree-node egtree new-node n b c)

应该

egtree eq

((n  (b  (c . new-node))))

(n  (b  (c . new-node)))

我已将其定义为功能

(defun set-tree-node (tree e &rest keys)
  (setcdr
   (reduce (lambda (xtree k)
             (message "tree %s k %s" xtree k)
             (assoc k (pushnew (list k) (cdr xtree) :key 'car)))
           keys :initial-value (cons nil tree))
   e))

但它只适用于现有列表

它可以成功更改(树,如果存在完整路径)

  egtree from


  (setq egtree '((n  (b  (c . d)))))

  egtree eq


  '((n  (b  (c . replaced-d))))

这样打电话后

  (set-tree-node jt 'replaced-d 'n 'b 'c)

但是如果完整路径没有,则此功能不适用于列表 退出

2 个答案:

答案 0 :(得分:1)

将宏写为:

(defmacro remacro (keys)
  (if keys
      `(abc ,(car keys)
            (remacro ,(cdr keys)))))

并称之为:

(remacro (a b c))

您不需要引用参数,因为不会评估宏参数。

要查看扩展,请使用:

(macroexpand-all '(remacro (a b c)))
(abc a (abc b (abc c nil)))

我不会在你的例子中看到add应该来自哪里,我认为这是abc的拼写错误。

答案 1 :(得分:0)

(defmacro tree-node (tree &rest keys)
  (if keys
      `(cdr
        (assoc ',(car (last keys))
               (pushnew
                ',(last keys)
                (tree-node ,tree ,@(butlast keys))
                :key 'car)))
    tree))


(setq egtree nil)
(setf (tree-node egtree l1 l2 lx) 'value)
(push (tree-node egtree l1 l2 ly) 'element1)
(push (tree-node egtree l1 l2 ly) 'element2)


(defmacro set-tree-node (tree value &rest keys)
  `(setf (tree-node ,tree ,@keys) ,value))


(set-tree-node egtree 'value l1 l2 lz)

希望像这样制作宏。