[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#66509: 29.1.50; let-alist should support numeric indexing
From: |
Spencer Baugh |
Subject: |
bug#66509: 29.1.50; let-alist should support numeric indexing |
Date: |
Thu, 12 Oct 2023 18:04:00 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
>From 28e52a343f72dddd991cafd23fea910cc5f64ac5 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <sbaugh@janestreet.com>
Date: Thu, 12 Oct 2023 18:01:46 -0400
Subject: [PATCH] Support numeric indexing in let-alist
let-alist is very useful. But sometimes an alist contains a list in
the middle, which contains yet more alists. Previously, this was
somewhat painful to deal with, and required something like:
(let-alist alist
(let-alist (nth 0 .a)
(let-alist (nth 3 .b)
.c)))
Now, the following works:
(let-alist alist
.a.0.b.3.c)
* lisp/emacs-lisp/let-alist.el (let-alist--access-sexp): Properly
parse numbers.
(let-alist--list-to-sexp): Use nth to handle numbers.
(let-alist): Update docs.
---
lisp/emacs-lisp/let-alist.el | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el
index d9ad46b2af7..de7c087bf2a 100644
--- a/lisp/emacs-lisp/let-alist.el
+++ b/lisp/emacs-lisp/let-alist.el
@@ -36,22 +36,23 @@
;; symbol inside body is let-bound to their cdrs in the alist. Dotted
;; symbol is any symbol starting with a `.'. Only those present in
;; the body are let-bound and this search is done at compile time.
+;; A number will result in a list index.
;;
;; For instance, the following code
;;
;; (let-alist alist
-;; (if (and .title .body)
+;; (if (and .title.0 .body)
;; .body
;; .site
;; .site.contents))
;;
;; essentially expands to
;;
-;; (let ((.title (cdr (assq 'title alist)))
+;; (let ((.title.0 (nth 0 (cdr (assq 'title alist))))
;; (.body (cdr (assq 'body alist)))
;; (.site (cdr (assq 'site alist)))
;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist))))))
-;; (if (and .title .body)
+;; (if (and .title.0 .body)
;; .body
;; .site
;; .site.contents))
@@ -93,14 +94,17 @@ let-alist--access-sexp
(if (string-match "\\`\\." name)
clean
(let-alist--list-to-sexp
- (mapcar #'intern (nreverse (split-string name "\\.")))
+ (mapcar #'read (nreverse (split-string name "\\.")))
variable))))
(defun let-alist--list-to-sexp (list var)
"Turn symbols LIST into recursive calls to `cdr' `assq' on VAR."
- `(cdr (assq ',(car list)
- ,(if (cdr list) (let-alist--list-to-sexp (cdr list) var)
- var))))
+ (let ((sym (car list))
+ (rest (if (cdr list) (let-alist--list-to-sexp (cdr list) var)
+ var)))
+ (cond
+ ((numberp sym) `(nth ,sym ,rest))
+ (t `(cdr (assq ',sym ,rest))))))
(defun let-alist--remove-dot (symbol)
"Return SYMBOL, sans an initial dot."
@@ -116,22 +120,23 @@ let-alist
"Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
Dotted symbol is any symbol starting with a `.'. Only those present
in BODY are let-bound and this search is done at compile time.
+A number will result in a list index.
For instance, the following code
(let-alist alist
- (if (and .title .body)
+ (if (and .title.0 .body)
.body
.site
.site.contents))
essentially expands to
- (let ((.title (cdr (assq \\='title alist)))
+ (let ((.title (nth 0 (cdr (assq \\='title alist))))
(.body (cdr (assq \\='body alist)))
(.site (cdr (assq \\='site alist)))
(.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist))))))
- (if (and .title .body)
+ (if (and .title.0 .body)
.body
.site
.site.contents))
--
2.39.3