* bug#74870: cl-labels and cl-flet don't create named blocks @ 2024-12-13 23:30 Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-14 16:54 ` Eli Zaretskii 0 siblings, 1 reply; 8+ messages in thread From: Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-13 23:30 UTC (permalink / raw) To: 74870 [-- Attachment #1: Type: text/plain, Size: 171 bytes --] In ANSI CL, these should create a named CL:BLOCK, allowing one to do a local return via CL:RETURN-FROM. In Emacs, this is not the case, resulting in an uncaught exception. [-- Attachment #2: Type: text/html, Size: 302 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-13 23:30 bug#74870: cl-labels and cl-flet don't create named blocks Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-14 16:54 ` Eli Zaretskii 2024-12-17 3:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-19 16:28 ` Michael Heerdegen via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 8+ messages in thread From: Eli Zaretskii @ 2024-12-14 16:54 UTC (permalink / raw) To: Jan Jouleodov, Stefan Monnier; +Cc: 74870 > Date: Fri, 13 Dec 2024 23:30:41 +0000 > From: Jan Jouleodov via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > In ANSI CL, these should create a named CL:BLOCK, allowing one to do a local return via > CL:RETURN-FROM. In Emacs, this is not the case, resulting in an uncaught exception. I'm guessing this is a documentation bug, in that this particular aspect of CL is not emulated by cl-labels. Stefan, am I right? ^ permalink raw reply [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-14 16:54 ` Eli Zaretskii @ 2024-12-17 3:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-19 0:55 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-19 16:28 ` Michael Heerdegen via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 8+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-17 3:23 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 74870, Jan Jouleodov >> In ANSI CL, these should create a named CL:BLOCK, allowing one to do a local return via >> CL:RETURN-FROM. In Emacs, this is not the case, resulting in an uncaught exception. > I'm guessing this is a documentation bug, in that this particular > aspect of CL is not emulated by cl-labels. > Stefan, am I right? Could be. Or it could be an oversight, maybe dating back to many many years ago, and that nobody noticed until now. Whichever was the original reason, now we get to decide whether we keep the behavior or not. Following Common Lisp's lead should not introduce any backward compatibility issue, all it would cost us is a slightly more costly macroexpansion for those macros. Stefan ^ permalink raw reply [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-17 3:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-19 0:55 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-21 15:44 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 8+ messages in thread From: Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-19 0:55 UTC (permalink / raw) To: Stefan Monnier; +Cc: Eli Zaretskii, 74870 > Whichever was the original reason, now we get to decide whether we keep > the behavior or not. Following Common Lisp's lead should not introduce any > backward compatibility issue, all it would cost us is a slightly more > costly macroexpansion for those macros. > > > Stefan Is there any reason why one would not want to *always* emulate the CL behavior in cl-lib? I could only think of a backward compatibility problem before CL was standardized, but I am not familiar with the time frame of cl-lib to know if that's really the case. ^ permalink raw reply [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-19 0:55 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-21 15:44 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-21 16:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 8+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-21 15:44 UTC (permalink / raw) To: Jan Jouleodov; +Cc: Eli Zaretskii, 74870 > Is there any reason why one would not want to *always* emulate the CL > behavior in cl-lib? I could only think of a backward compatibility > problem before CL was standardized, but I am not familiar with the time > frame of cl-lib to know if that's really the case. Could you try the patch below? Stefan diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 65bc2cb9173..73741417383 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2096,15 +2096,22 @@ cl-flet cl-declarations body))) (let ((binds ()) (newenv macroexpand-all-environment)) (dolist (binding bindings) - (let ((var (make-symbol (format "--cl-%s--" (car binding)))) - (args-and-body (cdr binding))) - (if (and (= (length args-and-body) 1) - (macroexp-copyable-p (car args-and-body))) + (let* ((var (make-symbol (format "--cl-%s--" (car binding)))) + (args-and-body (cdr binding)) + (args (car args-and-body)) + (body (cdr args-and-body))) + (if (and (null body) + (macroexp-copyable-p args)) ;; Optimize (cl-flet ((fun var)) body). - (setq var (car args-and-body)) - (push (list var (if (= (length args-and-body) 1) - (car args-and-body) - `(cl-function (lambda . ,args-and-body)))) + (setq var args) + (push (list var (if (null body) + args + (let ((parsed-body (macroexp-parse-body body))) + `(cl-function + (lambda ,args + ,@(car parsed-body) + (cl-block ,(car binding) + ,@(cdr parsed-body))))))) binds)) (push (cons (car binding) (lambda (&rest args) @@ -2300,7 +2307,13 @@ cl-labels var (macroexpand-all (if (null sbody) sargs ;A (FUNC EXP) definition. - `(cl-function (lambda ,sargs . ,sbody))) + (let ((parsed-body + (macroexp-parse-body sbody))) + `(cl-function + (lambda ,sargs + ,@(car parsed-body) + (cl-block ,var + ,@(cdr parsed-body)))))) newenv))))) (nreverse binds)) . ,(macroexp-unprogn ^ permalink raw reply related [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-21 15:44 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-21 16:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-21 16:24 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 8+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-21 16:14 UTC (permalink / raw) To: Jan Jouleodov; +Cc: Eli Zaretskii, 74870 [-- Attachment #1: Type: text/plain, Size: 385 bytes --] >> Is there any reason why one would not want to *always* emulate the CL >> behavior in cl-lib? I could only think of a backward compatibility >> problem before CL was standardized, but I am not familiar with the time >> frame of cl-lib to know if that's really the case. > Could you try the patch below? Never mind, it here's a better one I just pushed to `master`. Stefan [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: cl-labels.patch --] [-- Type: text/x-diff, Size: 5747 bytes --] commit 476426168106dbcee67d8ea667e11ebe80c7aaed Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Sat Dec 21 11:13:07 2024 -0500 (cl-flet, cl-labels): Fix bug#74870 * lisp/emacs-lisp/cl-macs.el (cl-flet, cl-labels): Wrap function bodies in `cl-block`. * test/lisp/emacs-lisp/cl-macs-tests.el (cl-macs--test-flet-block): New test. diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 65bc2cb9173..b1c42a23acd 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -2071,7 +2071,8 @@ cl-flet FUNC is the function name, and EXP is an expression that returns the function value to which it should be bound, or it can take the more common form (FUNC ARGLIST BODY...) which is a shorthand -for (FUNC (lambda ARGLIST BODY)). +for (FUNC (lambda ARGLIST BODY)) where BODY is wrapped in +a `cl-block' named FUNC. FUNC is defined only within FORM, not BODY, so you can't write recursive function definitions. Use `cl-labels' for that. See @@ -2096,15 +2097,22 @@ cl-flet cl-declarations body))) (let ((binds ()) (newenv macroexpand-all-environment)) (dolist (binding bindings) - (let ((var (make-symbol (format "--cl-%s--" (car binding)))) - (args-and-body (cdr binding))) - (if (and (= (length args-and-body) 1) - (macroexp-copyable-p (car args-and-body))) + (let* ((var (make-symbol (format "--cl-%s--" (car binding)))) + (args-and-body (cdr binding)) + (args (car args-and-body)) + (body (cdr args-and-body))) + (if (and (null body) + (macroexp-copyable-p args)) ;; Optimize (cl-flet ((fun var)) body). - (setq var (car args-and-body)) - (push (list var (if (= (length args-and-body) 1) - (car args-and-body) - `(cl-function (lambda . ,args-and-body)))) + (setq var args) + (push (list var (if (null body) + args + (let ((parsed-body (macroexp-parse-body body))) + `(cl-function + (lambda ,args + ,@(car parsed-body) + (cl-block ,(car binding) + ,@(cdr parsed-body))))))) binds)) (push (cons (car binding) (lambda (&rest args) @@ -2271,10 +2279,11 @@ cl-labels where EXP is a form that should return the function to bind to the function name FUNC, or (FUNC ARGLIST BODY...) where FUNC is the function name, ARGLIST its arguments, and BODY the -forms of the function body. FUNC is in scope in any BODY or EXP, as well -as FORM, so you can write recursive and mutually recursive -function definitions, with the caveat that EXPs are evaluated in sequence -and you cannot call a FUNC before its EXP has been evaluated. +forms of the function body. BODY is wrapped in a `cl-block' named FUNC. +FUNC is in scope in any BODY or EXP, as well as in FORM, so you can write +recursive and mutually recursive function definitions, with the caveat +that EXPs are evaluated in sequence and you cannot call a FUNC before its +EXP has been evaluated. See info node `(cl) Function Bindings' for details. \(fn ((FUNC ARGLIST BODY...) ...) FORM...)" @@ -2282,7 +2291,7 @@ cl-labels (let ((binds ()) (newenv macroexpand-all-environment)) (dolist (binding bindings) (let ((var (make-symbol (format "--cl-%s--" (car binding))))) - (push (cons var (cdr binding)) binds) + (push (cons var binding) binds) (push (cons (car binding) (lambda (&rest args) (if (eq (car args) cl--labels-magic) @@ -2295,12 +2304,18 @@ cl-labels ;; Perform self-tail call elimination. `(letrec ,(mapcar (lambda (bind) - (pcase-let* ((`(,var ,sargs . ,sbody) bind)) + (pcase-let* ((`(,var ,fun ,sargs . ,sbody) bind)) `(,var ,(cl--self-tco-on-form var (macroexpand-all (if (null sbody) sargs ;A (FUNC EXP) definition. - `(cl-function (lambda ,sargs . ,sbody))) + (let ((parsed-body + (macroexp-parse-body sbody))) + `(cl-function + (lambda ,sargs + ,@(car parsed-body) + (cl-block ,fun + ,@(cdr parsed-body)))))) newenv))))) (nreverse binds)) . ,(macroexp-unprogn diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el index 4baf5428101..e1a521dca79 100644 --- a/test/lisp/emacs-lisp/cl-macs-tests.el +++ b/test/lisp/emacs-lisp/cl-macs-tests.el @@ -718,6 +718,16 @@ cl-macs--labels (f lex-var))))) (should (equal (f nil) 'a))))) +(ert-deftest cl-macs--test-flet-block () + (should (equal (cl-block f1 + (cl-flet ((f1 (a) (cons (cl-return-from f1 a) 6))) + (cons (f1 5) 6))) + '(5 . 6))) + (should (equal (cl-block f1 + (cl-labels ((f1 (a) (cons (cl-return-from f1 a) 6))) + (cons (f1 7) 8))) + '(7 . 8)))) + (ert-deftest cl-flet/edebug () "Check that we can instrument `cl-flet' forms (bug#65344)." (with-temp-buffer ^ permalink raw reply related [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-21 16:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-21 16:24 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 0 replies; 8+ messages in thread From: Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-21 16:24 UTC (permalink / raw) To: Stefan Monnier; +Cc: Eli Zaretskii, 74870 > Never mind, it here's a better one I just pushed to `master`. > > > Stefan Cheers! ^ permalink raw reply [flat|nested] 8+ messages in thread
* bug#74870: cl-labels and cl-flet don't create named blocks 2024-12-14 16:54 ` Eli Zaretskii 2024-12-17 3:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-19 16:28 ` Michael Heerdegen via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 8+ messages in thread From: Michael Heerdegen via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-12-19 16:28 UTC (permalink / raw) To: Eli Zaretskii; +Cc: 74870, Stefan Monnier, Jan Jouleodov Eli Zaretskii <eliz@gnu.org> writes: > I'm guessing this is a documentation bug, in that this particular > aspect of CL is not emulated by cl-labels. I dug a bit into the history. `flet's implementation indeed lost its implicit `cl-block' in de7e2b36875 Get rid of cl-lexical-let, keeping only lexical-let for compatibility. Stefan Monnier <monnier@iro.umontreal.ca>, Thu Jun 7 2012 probably by accident. OTOH it looks like `cl-labels' never created implicit blocks. As the manual describes it as especially useful for recursive local function bindings, this case is maybe also a bit different. Michael. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-12-21 16:24 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-12-13 23:30 bug#74870: cl-labels and cl-flet don't create named blocks Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-14 16:54 ` Eli Zaretskii 2024-12-17 3:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-19 0:55 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-21 15:44 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-21 16:14 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-21 16:24 ` Jan Jouleodov via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-12-19 16:28 ` Michael Heerdegen via Bug reports for GNU Emacs, the Swiss army knife of text editors
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.