aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2021-01-20 14:12:50 -0500
committerStefan Monnier2021-01-20 14:13:15 -0500
commit0d3635536d4ed8ada6946e98e7d9f03fa443bc36 (patch)
treee63612c169f7a83cb0217c53f9d10722a8d063cc
parent66439d31ad2a63753d29e4582b76b36b9363d96b (diff)
downloademacs-0d3635536d4ed8ada6946e98e7d9f03fa443bc36.tar.gz
emacs-0d3635536d4ed8ada6946e98e7d9f03fa443bc36.zip
* lisp/emacs-lisp/subr-x.el (named-let): New macro
-rw-r--r--etc/NEWS12
-rw-r--r--lisp/emacs-lisp/subr-x.el22
2 files changed, 29 insertions, 5 deletions
diff --git a/etc/NEWS b/etc/NEWS
index c8cbce1882a..59b13998cfa 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1554,6 +1554,13 @@ buttons in it.
1554This function takes a string and returns a string propertized in a way 1554This function takes a string and returns a string propertized in a way
1555that makes it a valid button. 1555that makes it a valid button.
1556 1556
1557** subr-x
1558+++
1559*** A number of new string manipulation functions have been added.
1560'string-clean-whitespace', 'string-fill', 'string-limit',
1561'string-lines', 'string-pad' and 'string-chop-newline'.
1562
1563*** New macro `named-let` that provides Scheme's "named let" looping construct
1557 1564
1558** Miscellaneous 1565** Miscellaneous
1559 1566
@@ -1594,11 +1601,6 @@ length to a number).
1594This can be set to nil to inhibit hiding passwords in ".authinfo" files. 1601This can be set to nil to inhibit hiding passwords in ".authinfo" files.
1595 1602
1596+++ 1603+++
1597*** A number of new string manipulation functions have been added.
1598'string-clean-whitespace', 'string-fill', 'string-limit',
1599'string-lines', 'string-pad' and 'string-chop-newline'.
1600
1601+++
1602*** New variable 'current-minibuffer-command'. 1604*** New variable 'current-minibuffer-command'.
1603This is like 'this-command', but it is bound recursively when entering 1605This is like 'this-command', but it is bound recursively when entering
1604the minibuffer. 1606the minibuffer.
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index b90227da42f..a4514454c0b 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -389,6 +389,28 @@ it makes no sense to convert it to a string using
389 (set-buffer source-buffer) 389 (set-buffer source-buffer)
390 (replace-buffer-contents tmp-buffer max-secs max-costs))))))))) 390 (replace-buffer-contents tmp-buffer max-secs max-costs)))))))))
391 391
392(defmacro named-let (name bindings &rest body)
393 "Looping construct taken from Scheme.
394Like `let', bind variables in BINDINGS and then evaluate BODY,
395but with the twist that BODY can evaluate itself recursively by
396calling NAME, where the arguments passed to NAME are used
397as the new values of the bound variables in the recursive invocation."
398 (declare (indent 2) (debug (symbolp (&rest (symbolp form)) body)))
399 (require 'cl-lib)
400 (let ((fargs (mapcar (lambda (b) (if (consp b) (car b) b)) bindings))
401 (aargs (mapcar (lambda (b) (if (consp b) (cadr b))) bindings)))
402 ;; According to the Scheme semantics of named let, `name' is not in scope
403 ;; while evaluating the expressions in `bindings', and for this reason, the
404 ;; "initial" function call below needs to be outside of the `cl-labels'.
405 ;; When the "self-tco" eliminates all recursive calls, the `cl-labels'
406 ;; expands to a lambda which the byte-compiler then combines with the
407 ;; funcall to make a `let' so we end up with a plain `while' loop and no
408 ;; remaining `lambda' at all.
409 `(funcall
410 (cl-labels ((,name ,fargs . ,body)) #',name)
411 . ,aargs)))
412
413
392(provide 'subr-x) 414(provide 'subr-x)
393 415
394;;; subr-x.el ends here 416;;; subr-x.el ends here