aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Malabarba2014-12-10 10:15:22 -0500
committerTed Zlatanov2014-12-10 13:59:11 -0500
commita5b477aa92e4b76896efa57f9bd62912bd92dd02 (patch)
tree9bf2e79077ba2f0af1e944ffe3aad3752b1185a4
parentf3e16cbb5258fcbe2969eb48b332b2c629cfb2a6 (diff)
downloademacs-a5b477aa92e4b76896efa57f9bd62912bd92dd02.tar.gz
emacs-a5b477aa92e4b76896efa57f9bd62912bd92dd02.zip
Add let-alist macro and package.
* let-alist.el: Add new package and macro.
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/let-alist.el110
2 files changed, 114 insertions, 0 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index d5f22541dcf..e65835cfb93 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
12014-12-10 Artur Malabarba <bruce.connor.am@gmail.com>
2
3 * let-alist.el: Add new package and macro.
4
12014-12-10 Eric S. Raymond <esr@snark.thyrsus.com> 52014-12-10 Eric S. Raymond <esr@snark.thyrsus.com>
2 6
3 * vc/vc-dispatcher.el, vc/vc-hooks.el, vc/vc-rcs.el, 7 * vc/vc-dispatcher.el, vc/vc-hooks.el, vc/vc-rcs.el,
diff --git a/lisp/let-alist.el b/lisp/let-alist.el
new file mode 100644
index 00000000000..1cf5c27af3e
--- /dev/null
+++ b/lisp/let-alist.el
@@ -0,0 +1,110 @@
1;;; let-alist.el --- Easily let-bind values of an assoc-list by their names.
2
3;; Copyright (C) 2014 Free Software Foundation, Inc.
4
5;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
6;; Maintainer: Artur Malabarba <bruce.connor.am@gmail.com>
7;; Version: 1.0
8;; Keywords: extensions lisp
9;; Prefix: let-alist
10;; Separator: -
11
12;;; Commentary:
13;;
14;; This package offers a single macro, `let-alist'. This macro takes a
15;; first argument (whose value must be an alist) and a body.
16;;
17;; The macro expands to a let form containing body, where each dotted
18;; symbol inside body is let-bound to their cdrs in the alist. Dotted
19;; symbol is any symbol starting with a `.'. Only those present in
20;; the body are let-bound and this search is done at compile time.
21;;
22;; For instance, the following code
23;;
24;; (let-alist alist
25;; (if (and .title .body)
26;; .body
27;; .site))
28;;
29;; expands to
30;;
31;; (let ((.title (cdr (assq 'title alist)))
32;; (.body (cdr (assq 'body alist)))
33;; (.site (cdr (assq 'site alist))))
34;; (if (and .title .body)
35;; .body
36;; .site))
37;;
38;; Note that only one level is supported. If you nest `let-alist'
39;; invocations, the inner one can't access the variables of the outer
40;; one.
41
42;;; License:
43;;
44;; This file is part of GNU Emacs.
45;;
46;; GNU Emacs is free software: you can redistribute it and/or modify
47;; it under the terms of the GNU General Public License as published by
48;; the Free Software Foundation, either version 3 of the License, or
49;; (at your option) any later version.
50;;
51;; GNU Emacs is distributed in the hope that it will be useful,
52;; but WITHOUT ANY WARRANTY; without even the implied warranty of
53;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54;; GNU General Public License for more details.
55;;
56;; You should have received a copy of the GNU General Public License
57;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
58
59;;; Code:
60
61
62(defun let-alist--deep-dot-search (data)
63 "Return alist of symbols inside DATA which start with a `.'.
64Perform a deep search and return an alist where each car is the
65symbol, and each cdr is the same symbol without the `.'."
66 (cond
67 ((symbolp data)
68 (let ((name (symbol-name data)))
69 (when (string-match "\\`\\." name)
70 ;; Return the cons cell inside a list, so it can be appended
71 ;; with other results in the clause below.
72 (list (cons data (intern (replace-match "" nil nil name)))))))
73 ((not (listp data)) nil)
74 (t (apply #'append
75 (remove nil (mapcar #'let-alist--deep-dot-search data))))))
76
77;;;###autoload
78(defmacro let-alist (alist &rest body)
79 "Let-bind dotted symbols to their cdrs in ALIST and execute BODY.
80Dotted symbol is any symbol starting with a `.'. Only those
81present in BODY are let-bound and this search is done at compile
82time.
83
84For instance, the following code
85
86 (let-alist alist
87 (if (and .title .body)
88 .body
89 .site))
90
91expands to
92
93 (let ((.title (cdr (assq 'title alist)))
94 (.body (cdr (assq 'body alist)))
95 (.site (cdr (assq 'site alist))))
96 (if (and .title .body)
97 .body
98 .site))"
99 (declare (indent 1) (debug t))
100 `(let ,(mapcar (lambda (x) `(,(car x) (cdr (assq ',(cdr x) ,alist))))
101 (delete-dups (let-alist--deep-dot-search body)))
102 ,@body))
103
104(provide 'let-alist)
105
106;; Local Variables:
107;; sentence-end-double-space: t
108;; End:
109
110;;; let-alist.el ends here