From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Stuart D. Herring" Newsgroups: gmane.emacs.devel Subject: RFC: `macro-eval' Date: Wed, 30 Aug 2006 10:11:43 -0700 (PDT) Message-ID: <43976.128.165.123.18.1156957903.squirrel@webmail.lanl.gov> Reply-To: herring@lanl.gov NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain;charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Trace: sea.gmane.org 1156957948 29712 80.91.229.2 (30 Aug 2006 17:12:28 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 30 Aug 2006 17:12:28 +0000 (UTC) Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Aug 30 19:12:25 2006 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1GITbd-0007Pi-1s for ged-emacs-devel@m.gmane.org; Wed, 30 Aug 2006 19:12:01 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GITbc-00055d-EE for ged-emacs-devel@m.gmane.org; Wed, 30 Aug 2006 13:12:00 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1GITbR-000556-RA for emacs-devel@gnu.org; Wed, 30 Aug 2006 13:11:49 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1GITbP-00053C-O0 for emacs-devel@gnu.org; Wed, 30 Aug 2006 13:11:49 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GITbP-000530-GJ for emacs-devel@gnu.org; Wed, 30 Aug 2006 13:11:47 -0400 Original-Received: from [192.65.95.54] (helo=mailwasher-b.lanl.gov) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA:32) (Exim 4.52) id 1GITkq-0001Wj-Bi for emacs-devel@gnu.org; Wed, 30 Aug 2006 13:21:32 -0400 Original-Received: from mailrelay2.lanl.gov (mailrelay2.lanl.gov [128.165.4.103]) by mailwasher-b.lanl.gov (8.13.6/8.13.6/(ccn-5)) with ESMTP id k7UHBiMt024572 for ; Wed, 30 Aug 2006 11:11:44 -0600 Original-Received: from webmail1.lanl.gov (webmail1.lanl.gov [128.165.4.106]) by mailrelay2.lanl.gov (8.13.6/8.13.6/(ccn-5)) with ESMTP id k7UHBhVm016751 for ; Wed, 30 Aug 2006 11:11:43 -0600 Original-Received: from webmail1.lanl.gov (localhost.localdomain [127.0.0.1]) by webmail1.lanl.gov (8.12.11.20060308/8.12.11) with ESMTP id k7UHBhNo016647 for ; Wed, 30 Aug 2006 11:11:43 -0600 Original-Received: (from apache@localhost) by webmail1.lanl.gov (8.12.11.20060308/8.12.11/Submit) id k7UHBhWA016645; Wed, 30 Aug 2006 10:11:43 -0700 X-Authentication-Warning: webmail1.lanl.gov: apache set sender to herring@lanl.gov using -f Original-Received: from 128.165.123.18 (SquirrelMail authenticated user 196434) by webmail.lanl.gov with HTTP; Wed, 30 Aug 2006 10:11:43 -0700 (PDT) Original-To: emacs-devel@gnu.org User-Agent: SquirrelMail/1.4.6-7.el3.7lanl X-Priority: 3 (Normal) Importance: Normal X-PMX-Version: 4.7.1.128075 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:59115 Archived-At: I wrote a macro to automatically generate the boilerplate "delayed evaluation with uninterned symbol" code needed in many macros (and described at (elisp)Surprising Local Vars), which I present for comment. As far as my testing shows, it works both in interpreted and compiled environments, with the one caveat that, as it uses `progv', it both requires the cl library at runtime and generates spurious warnings upon compilation because the byte compiler doesn't recognize that `progv' binds variables. (This of course is not easily fixed, since `progv' can calculate the lists of variables to bind at runtime!) (put 'macro-eval 'lisp-indent-function 1) (defmacro macro-eval (spec &rest body) "Eval BODY with symbols in SPEC bound to temporary symbols. For use in macros. Each element of SPEC looks like VAR or (VAR VAL). At reevaluation time, each symbol will be bound to the evaluated form of the corresponding VAL, or to the evaluated form of VAR's value if no VAL. Note that evaluation and binding occurs like `let' and not `let*'." (let* ((vars (mapcar (lambda (e) (or (car-safe e) e)) spec)) (vals (mapcar (lambda (e) (if (consp e) `',(cadr e) e)) spec)) (syms (mapcar 'gensym (mapcar 'symbol-name vars))) (comma '\,)) (list '\` `(progv ',syms (mapcar 'eval ',(list comma `(mapcar 'eval ',vals))) ,(list comma `(progv ',vars ',syms ,@body)))))) With this, it becomes possible to write the example `for' macro thusly: (defmacro inc (var) `(setq ,var (1+ ,var))) (defmacro for (var from init to final do &rest body) "Execute a simple for loop: (for i from 1 to 10 do (print i))." ;; We evaluate init this way to provide the correct evaluation order. (macro-eval (init final) `(let ((,var ,init)) (while (<= ,var ,final) ,@body (inc ,var))))) The savings in code are more pronounced when the macro does not bind client variables, as often the `let's can be discarded entirely. I'm quite willing to believe there are better ways of achieving this; improvements and suggestions are welcome. (For instance, is it possible to do without the `comma' variable?) If it seems useful, I can also implement a `progv'-like macro that requires static variable selection so the compiler might be happier. (Of course, let me know if that already exists!) Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping.