简体   繁体   中英

Elisp recursive macro

Trying to define resursive macro in elisp

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



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

But it is ended up in

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

error.

Wanted to get result like

(func1 a (func1 b (func1 c nil nil) '(c)) '(b c))

from

(remacro '(a b c))

Please let me know how I can correct this definition.

One more thing could I defined `keys' as rest parameter like

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

tried this one but it is not working.

USE CASE:

Basically I wanted to define a function

to set a tree node that is arranged in alist way

(it is still not working, have to work on it)

(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)

After running

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

should get

egtree eq

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

or

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

I had defined it as function

(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))

But it could work only for existing list

It can successfully change (tree if full path exists)

  egtree from


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

to

  egtree eq


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

after called like this

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

But this function do not work with if list if complete path do not exits

Write the macro as:

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

and call it:

(remacro (a b c))

You don't need to quote the argument because macro parameters are not evaluated.

To see the expansion, use:

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

I don't see where add is supposed to come from in your example, I assume that was a typo for abc .

(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)

wanted to make macro like this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM