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 to handle lists. (Bug#66509) (let-alist--list-to-sexp): Use nth to handle numbers. (let-alist): Update docs.
This commit is contained in:
parent
252ed22d62
commit
ae4171efdc
1 changed files with 15 additions and 10 deletions
|
@ -36,22 +36,23 @@
|
||||||
;; symbol inside body is let-bound to their cdrs in the alist. Dotted
|
;; symbol inside body is let-bound to their cdrs in the alist. Dotted
|
||||||
;; symbol is any symbol starting with a `.'. Only those present in
|
;; symbol is any symbol starting with a `.'. Only those present in
|
||||||
;; the body are let-bound and this search is done at compile time.
|
;; 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
|
;; For instance, the following code
|
||||||
;;
|
;;
|
||||||
;; (let-alist alist
|
;; (let-alist alist
|
||||||
;; (if (and .title .body)
|
;; (if (and .title.0 .body)
|
||||||
;; .body
|
;; .body
|
||||||
;; .site
|
;; .site
|
||||||
;; .site.contents))
|
;; .site.contents))
|
||||||
;;
|
;;
|
||||||
;; essentially expands to
|
;; essentially expands to
|
||||||
;;
|
;;
|
||||||
;; (let ((.title (cdr (assq 'title alist)))
|
;; (let ((.title.0 (nth 0 (cdr (assq 'title alist))))
|
||||||
;; (.body (cdr (assq 'body alist)))
|
;; (.body (cdr (assq 'body alist)))
|
||||||
;; (.site (cdr (assq 'site alist)))
|
;; (.site (cdr (assq 'site alist)))
|
||||||
;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist))))))
|
;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist))))))
|
||||||
;; (if (and .title .body)
|
;; (if (and .title.0 .body)
|
||||||
;; .body
|
;; .body
|
||||||
;; .site
|
;; .site
|
||||||
;; .site.contents))
|
;; .site.contents))
|
||||||
|
@ -93,14 +94,17 @@ symbol, and each cdr is the same symbol without the `.'."
|
||||||
(if (string-match "\\`\\." name)
|
(if (string-match "\\`\\." name)
|
||||||
clean
|
clean
|
||||||
(let-alist--list-to-sexp
|
(let-alist--list-to-sexp
|
||||||
(mapcar #'intern (nreverse (split-string name "\\.")))
|
(mapcar #'read (nreverse (split-string name "\\.")))
|
||||||
variable))))
|
variable))))
|
||||||
|
|
||||||
(defun let-alist--list-to-sexp (list var)
|
(defun let-alist--list-to-sexp (list var)
|
||||||
"Turn symbols LIST into recursive calls to `cdr' `assq' on VAR."
|
"Turn symbols LIST into recursive calls to `cdr' `assq' on VAR."
|
||||||
`(cdr (assq ',(car list)
|
(let ((sym (car list))
|
||||||
,(if (cdr list) (let-alist--list-to-sexp (cdr list) var)
|
(rest (if (cdr list) (let-alist--list-to-sexp (cdr list) var)
|
||||||
var))))
|
var)))
|
||||||
|
(cond
|
||||||
|
((numberp sym) `(nth ,sym ,rest))
|
||||||
|
(t `(cdr (assq ',sym ,rest))))))
|
||||||
|
|
||||||
(defun let-alist--remove-dot (symbol)
|
(defun let-alist--remove-dot (symbol)
|
||||||
"Return SYMBOL, sans an initial dot."
|
"Return SYMBOL, sans an initial dot."
|
||||||
|
@ -116,22 +120,23 @@ symbol, and each cdr is the same symbol without the `.'."
|
||||||
"Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
|
"Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
|
||||||
Dotted symbol is any symbol starting with a `.'. Only those present
|
Dotted symbol is any symbol starting with a `.'. Only those present
|
||||||
in BODY are let-bound and this search is done at compile time.
|
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
|
For instance, the following code
|
||||||
|
|
||||||
(let-alist alist
|
(let-alist alist
|
||||||
(if (and .title .body)
|
(if (and .title.0 .body)
|
||||||
.body
|
.body
|
||||||
.site
|
.site
|
||||||
.site.contents))
|
.site.contents))
|
||||||
|
|
||||||
essentially expands to
|
essentially expands to
|
||||||
|
|
||||||
(let ((.title (cdr (assq \\='title alist)))
|
(let ((.title (nth 0 (cdr (assq \\='title alist))))
|
||||||
(.body (cdr (assq \\='body alist)))
|
(.body (cdr (assq \\='body alist)))
|
||||||
(.site (cdr (assq \\='site alist)))
|
(.site (cdr (assq \\='site alist)))
|
||||||
(.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist))))))
|
(.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist))))))
|
||||||
(if (and .title .body)
|
(if (and .title.0 .body)
|
||||||
.body
|
.body
|
||||||
.site
|
.site
|
||||||
.site.contents))
|
.site.contents))
|
||||||
|
|
Loading…
Reference in a new issue