help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

question on elisp best practive


From: Aemon
Subject: question on elisp best practive
Date: Tue, 09 Oct 2007 11:07:56 -0700
User-agent: G2/1.0

Hi all,

I've got a lot of code that traverses trees and does something at
every node. I'd like to abstract the traversal part of the code, and
just pass in the bit that does the action. Something like:

(defun visit-each (tree func depth)
  (funcall func tree depth)
  (dolist (ea (tree-children tree))
    (visit-each ea (+ 1 depth))))


This seems to work pretty well, called like so:

(visit-each my-tree
            (lambda (subtree depth)
              (message "%s %s" subtree depth)))


However, as it's not a closure I'm passing in, I would get into
trouble if I tried:

(visit-each my-tree
            (let ((depth "my depth"))
              (lambda (subtree)
                (message "%s %s" subtree depth))))

Elisp's dynamic scope would cause my local binding of 'depth' -> "my
depth" to always be shadowed.

Which sucks, because there is often extra information that I need to
pass into the lambda somehow, but I can't reliably reference it
without being aware of which variable names the traversal function is
binding.

So now I'm thinking the best thing is to do the traversal iteratively,
inline, in a macro, and take special care to gensym all of my macro
variables.

Something like:


(defmacro visit-each (tree depth each-tree-form &rest body)
  (let ((tree-form (gensym))
        (stack-form (gensym))
        (tmp-child-form (gensym)))
        `(let* ((,tree-form ,tree)
                (,stack-form (list ,tree-form)))
           (while (not (null ,stack-form))
             (let ((,each-tree-form (pop ,stack-form)))
               ,@body)
             (dolist (,tmp-child-form (children-of ,tree-form))
               (push ,tmp-child-form ,stack-form))))))


Is there a better way to do this?

Thanks!

Aemon



reply via email to

[Prev in Thread] Current Thread [Next in Thread]