diff options
| author | Artur Malabarba | 2014-12-19 18:25:06 -0200 |
|---|---|---|
| committer | Artur Malabarba | 2014-12-19 18:30:26 -0200 |
| commit | f447d33fdb082ce8e5d336be6034df24339b4c45 (patch) | |
| tree | 7ad100c335eb0e84024c0aab266f674e2078ff47 /lisp | |
| parent | 948fa912de164a1374c87e9206cddca741b7fa33 (diff) | |
| download | emacs-f447d33fdb082ce8e5d336be6034df24339b4c45.tar.gz emacs-f447d33fdb082ce8e5d336be6034df24339b4c45.zip | |
* let-alist.el (let-alist): Enable access to deeper alists
Acces them by using extra dots inside the dotted symbols.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 5 | ||||
| -rw-r--r-- | lisp/let-alist.el | 71 |
2 files changed, 59 insertions, 17 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 12530a997ba..b658cc1d0fa 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2014-12-19 Artur Malabarba <bruce.connor.am@gmail.com> | ||
| 2 | |||
| 3 | * let-alist.el (let-alist): Enable access to deeper alists by | ||
| 4 | using dots inside the dotted symbols. | ||
| 5 | |||
| 1 | 2014-12-19 Alan Mackenzie <acm@muc.de> | 6 | 2014-12-19 Alan Mackenzie <acm@muc.de> |
| 2 | 7 | ||
| 3 | Make C++11 uniform init syntax work. New keywords "final" and "override" | 8 | Make C++11 uniform init syntax work. New keywords "final" and "override" |
diff --git a/lisp/let-alist.el b/lisp/let-alist.el index 813b8417aaa..692beba16dd 100644 --- a/lisp/let-alist.el +++ b/lisp/let-alist.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ;; Author: Artur Malabarba <bruce.connor.am@gmail.com> | 5 | ;; Author: Artur Malabarba <bruce.connor.am@gmail.com> |
| 6 | ;; Maintainer: Artur Malabarba <bruce.connor.am@gmail.com> | 6 | ;; Maintainer: Artur Malabarba <bruce.connor.am@gmail.com> |
| 7 | ;; Version: 1.0.1 | 7 | ;; Version: 1.0.2 |
| 8 | ;; Keywords: extensions lisp | 8 | ;; Keywords: extensions lisp |
| 9 | ;; Prefix: let-alist | 9 | ;; Prefix: let-alist |
| 10 | ;; Separator: - | 10 | ;; Separator: - |
| @@ -39,21 +39,25 @@ | |||
| 39 | ;; (let-alist alist | 39 | ;; (let-alist alist |
| 40 | ;; (if (and .title .body) | 40 | ;; (if (and .title .body) |
| 41 | ;; .body | 41 | ;; .body |
| 42 | ;; .site)) | 42 | ;; .site |
| 43 | ;; .site.contents)) | ||
| 43 | ;; | 44 | ;; |
| 44 | ;; expands to | 45 | ;; essentially expands to |
| 45 | ;; | 46 | ;; |
| 46 | ;; (let ((.title (cdr (assq 'title alist))) | 47 | ;; (let ((.title (cdr (assq 'title alist))) |
| 47 | ;; (.body (cdr (assq 'body alist))) | 48 | ;; (.body (cdr (assq 'body alist))) |
| 48 | ;; (.site (cdr (assq 'site alist)))) | 49 | ;; (.site (cdr (assq 'site alist))) |
| 50 | ;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) | ||
| 49 | ;; (if (and .title .body) | 51 | ;; (if (and .title .body) |
| 50 | ;; .body | 52 | ;; .body |
| 51 | ;; .site)) | 53 | ;; .site |
| 54 | ;; .site.contents)) | ||
| 55 | ;; | ||
| 56 | ;; If you nest `let-alist' invocations, the inner one can't access | ||
| 57 | ;; the variables of the outer one. You can, however, access alists | ||
| 58 | ;; inside the original alist by using dots inside the symbol, as | ||
| 59 | ;; displayed in the example above by the `.site.contents'. | ||
| 52 | ;; | 60 | ;; |
| 53 | ;; Note that only one level is supported. If you nest `let-alist' | ||
| 54 | ;; invocations, the inner one can't access the variables of the outer | ||
| 55 | ;; one. | ||
| 56 | |||
| 57 | ;;; Code: | 61 | ;;; Code: |
| 58 | 62 | ||
| 59 | 63 | ||
| @@ -72,6 +76,31 @@ symbol, and each cdr is the same symbol without the `.'." | |||
| 72 | (t (apply #'append | 76 | (t (apply #'append |
| 73 | (mapcar #'let-alist--deep-dot-search data))))) | 77 | (mapcar #'let-alist--deep-dot-search data))))) |
| 74 | 78 | ||
| 79 | (defun let-alist--access-sexp (symbol variable) | ||
| 80 | "Return a sexp used to acess SYMBOL inside VARIABLE." | ||
| 81 | (let* ((clean (let-alist--remove-dot symbol)) | ||
| 82 | (name (symbol-name clean))) | ||
| 83 | (if (string-match "\\`\\." name) | ||
| 84 | clean | ||
| 85 | (let-alist--list-to-sexp | ||
| 86 | (mapcar #'intern (nreverse (split-string name "\\."))) | ||
| 87 | variable)))) | ||
| 88 | |||
| 89 | (defun let-alist--list-to-sexp (list var) | ||
| 90 | "Turn symbols LIST into recursive calls to `cdr' `assq' on VAR." | ||
| 91 | `(cdr (assq ',(car list) | ||
| 92 | ,(if (cdr list) (let-alist--list-to-sexp (cdr list) var) | ||
| 93 | var)))) | ||
| 94 | |||
| 95 | (defun let-alist--remove-dot (symbol) | ||
| 96 | "Return SYMBOL, sans an initial dot." | ||
| 97 | (let ((name (symbol-name symbol))) | ||
| 98 | (if (string-match "\\`\\." name) | ||
| 99 | (intern (replace-match "" nil nil name)) | ||
| 100 | symbol))) | ||
| 101 | |||
| 102 | |||
| 103 | ;;; The actual macro. | ||
| 75 | ;;;###autoload | 104 | ;;;###autoload |
| 76 | (defmacro let-alist (alist &rest body) | 105 | (defmacro let-alist (alist &rest body) |
| 77 | "Let-bind dotted symbols to their cdrs in ALIST and execute BODY. | 106 | "Let-bind dotted symbols to their cdrs in ALIST and execute BODY. |
| @@ -83,20 +112,28 @@ For instance, the following code | |||
| 83 | (let-alist alist | 112 | (let-alist alist |
| 84 | (if (and .title .body) | 113 | (if (and .title .body) |
| 85 | .body | 114 | .body |
| 86 | .site)) | 115 | .site |
| 116 | .site.contents)) | ||
| 87 | 117 | ||
| 88 | expands to | 118 | essentially expands to |
| 89 | 119 | ||
| 90 | (let ((.title (cdr (assq 'title alist))) | 120 | (let ((.title (cdr (assq 'title alist))) |
| 91 | (.body (cdr (assq 'body alist))) | 121 | (.body (cdr (assq 'body alist))) |
| 92 | (.site (cdr (assq 'site alist)))) | 122 | (.site (cdr (assq 'site alist))) |
| 123 | (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) | ||
| 93 | (if (and .title .body) | 124 | (if (and .title .body) |
| 94 | .body | 125 | .body |
| 95 | .site))" | 126 | .site |
| 127 | .site.contents)) | ||
| 128 | |||
| 129 | If you nest `let-alist' invocations, the inner one can't access | ||
| 130 | the variables of the outer one. You can, however, access alists | ||
| 131 | inside the original alist by using dots inside the symbol, as | ||
| 132 | displayed in the example above." | ||
| 96 | (declare (indent 1) (debug t)) | 133 | (declare (indent 1) (debug t)) |
| 97 | (let ((var (gensym "let-alist"))) | 134 | (let ((var (gensym "alist"))) |
| 98 | `(let ((,var ,alist)) | 135 | `(let ((,var ,alist)) |
| 99 | (let ,(mapcar (lambda (x) `(,(car x) (cdr (assq ',(cdr x) ,var)))) | 136 | (let ,(mapcar (lambda (x) `(,(car x) ,(let-alist--access-sexp (car x) var))) |
| 100 | (delete-dups (let-alist--deep-dot-search body))) | 137 | (delete-dups (let-alist--deep-dot-search body))) |
| 101 | ,@body)))) | 138 | ,@body)))) |
| 102 | 139 | ||