[Top][All Lists]

[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

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

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)))
             (dolist (,tmp-child-form (children-of ,tree-form))
               (push ,tmp-child-form ,stack-form))))))

Is there a better way to do this?



reply via email to

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