From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: pjb@informatimago.com (Pascal J. Bourguignon) Newsgroups: gmane.emacs.help Subject: Re: Expected behavior of CL special forms, 'labels' and 'flet', inside macros. Date: Tue, 04 Aug 2009 03:49:38 +0200 Organization: Informatimago Message-ID: <87r5vs8i19.fsf@galatea.local> References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1249354176 25701 80.91.229.12 (4 Aug 2009 02:49:36 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 4 Aug 2009 02:49:36 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Tue Aug 04 04:49:30 2009 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 1MYA5h-0005ts-K3 for geh-help-gnu-emacs@m.gmane.org; Tue, 04 Aug 2009 04:49:29 +0200 Original-Received: from localhost ([127.0.0.1]:57363 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MYA5g-0006ei-V2 for geh-help-gnu-emacs@m.gmane.org; Mon, 03 Aug 2009 22:49:28 -0400 Original-Path: news.stanford.edu!newsfeed.stanford.edu!goblin2!goblin.stu.neva.ru!newsfeed.freenet.de!bolzen.all.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail Original-Newsgroups: gnu.emacs.help Original-Lines: 104 Original-X-Trace: individual.net bm69y1l4thYEY9UvjvPqiAxCO4ayM3WDFbi+h24UvYhWNi8Vko Cancel-Lock: sha1:YTE2ZGQxYTczNDM5Nzg3NzBkZDNmMGE1YjdlNDRjOWJmNmFiZTMwZQ== sha1:8ROQesfR7dGrCqO99PZ9bhlY4ws= Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en X-Disabled: X-No-Archive: no User-Agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/22.3 (darwin) Original-Xref: news.stanford.edu gnu.emacs.help:171540 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:66720 Archived-At: Jon Strait writes: > Hello, > > I thought I'd run this issue by the list in case someone who's worked > on the CL extension code can say that it's the proper behavior and not > worth submitting a bug report on. > > Basically, I tried using a 'labels' form to bind a function inside a > macro to be used recursively and it wasn't working. (Lisp nesting > exceeds max error) Then, I switched the 'labels' with 'flet', which > ended up working fine, but not until after having to change the > binding name as well. Using the same name for 'flet' as was previous > used for 'labels' resulted in this strange error: If you have a look at the macroexpansions, you will see that flet shadows the original function name (and therefore it's understandable that emacs lisp has difficulties if it was a macro), while labels makes a substitution of the occurences of the defined functions. > "Use `labels', not `flet', to rebind macro names" > > Is seems for some reason, the 'labels' functions binding name was > registered with a macro name as well. This could be considered a bug (vs. CL), or at least a feature request, to have flet be able to shadow macros. > Be advised, this is only in the context of testing both the macro and > the calling code with eval-last-sexp inside a buffer. > > For the sample macro I created below, the first argument is a list of > items and every subsequent argument is a lambda function taking one > argument, to apply in sequence to the initial argument list using > mapcar: > > (defmacro map-chain (init-list &rest mfuncs) > (setq mfuncs (reverse mfuncs)) > (flet ((fmap (init-list mfuncs) > (if (null mfuncs) > init-list > `(mapcar ,(car mfuncs) ,(fmap init-list (cdr mfuncs)))))) > (fmap init-list mfuncs))) Or use let instead of setq: (defmacro map-chain (init-list &rest mfuncs) (let ((mfuncs (reverse mfuncs))) (flet ((fmap (init-list mfuncs) (if (null mfuncs) init-list `(mapcar ,(car mfuncs) ,(fmap init-list (cdr mfuncs)))))) (fmap init-list mfuncs)))) If flet was implemented with the same semantics as in Common Lips, that macro wouldn't work. Indeed, you'd better use labels. In Common Lisp: C/USER[319]> (macroexpand '(map-chain '(7 8 9) (lambda (x) (* x 10)) (lambda (y) (+ y 4)))) *** - EVAL: undefined function FMAP It works in emacs lisp because flet is implemented as a dynamic binding, and therefore when fmap is executing, fmap is fbound to the redefinition. In Common Lisp: C/USER[322]> (defun example (x) (list 'toplevel x)) EXAMPLE C/USER[323]> (flet ((example (x) (if (oddp x) (list 'lexical 'example x) (example (1- x))))) (values (example 1) (example 2))) (LEXICAL EXAMPLE 1) ; (TOPLEVEL 1) Both calls to example (example 1) and (example 2) call the lexical local function. With x bound to 1, the first list is returned directly; with x bound to 2, the toplevel function is called, from the local funciton. In emacs lisp: (defun example (x) (list 'toplevel x)) --> example (flet ((example (x) (if (oddp x) (list 'lexical 'example x) (example (1- x))))) (values (example 1) (example 2))) --> ((lexical example 1) (lexical example 1)) is not what was expected from (require 'cl)... You could report a bug, but again, if you really want Common Lisp semantics, it might be better to use emacs-cl. -- __Pascal Bourguignon__