From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Aemon Newsgroups: gmane.emacs.help Subject: question on elisp best practive Date: Tue, 09 Oct 2007 11:07:56 -0700 Organization: http://groups.google.com Message-ID: <1191953276.499830.12710@22g2000hsm.googlegroups.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: sea.gmane.org 1192017308 25465 80.91.229.12 (10 Oct 2007 11:55:08 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 10 Oct 2007 11:55:08 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Wed Oct 10 13:55:07 2007 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1Ifa9X-0005A8-3Z for geh-help-gnu-emacs@m.gmane.org; Wed, 10 Oct 2007 13:55:03 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ifa9R-0001T1-Hg for geh-help-gnu-emacs@m.gmane.org; Wed, 10 Oct 2007 07:54:57 -0400 Original-Path: shelby.stanford.edu!newsfeed.stanford.edu!postnews.google.com!22g2000hsm.googlegroups.com!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 61 Original-NNTP-Posting-Host: 216.57.20.61 Original-X-Trace: posting.google.com 1191953276 334 127.0.0.1 (9 Oct 2007 18:07:56 GMT) Original-X-Complaints-To: groups-abuse@google.com Original-NNTP-Posting-Date: Tue, 9 Oct 2007 18:07:56 +0000 (UTC) User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7,gzip(gfe),gzip(gfe) Complaints-To: groups-abuse@google.com Injection-Info: 22g2000hsm.googlegroups.com; posting-host=216.57.20.61; posting-account=ps2QrAMAAAA6_jCuRt2JEIpn5Otqf_w0 Original-Xref: shelby.stanford.edu gnu.emacs.help:152766 X-Mailman-Approved-At: Wed, 10 Oct 2007 07:53:27 -0400 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:48294 Archived-At: 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