[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/dash 2db56f5 424/439: [-let] Add support for &as bindin
From: |
Phillip Lord |
Subject: |
[elpa] externals/dash 2db56f5 424/439: [-let] Add support for &as bindings (#115) |
Date: |
Tue, 04 Aug 2015 20:31:39 +0000 |
branch: externals/dash
commit 2db56f59aca3bc85cc35944480dcbdf1a5607283
Author: Matus Goljer <address@hidden>
Commit: Matus Goljer <address@hidden>
[-let] Add support for &as bindings (#115)
---
README.md | 40 +++++++++++++++++++++++++++++++++++++
dash.el | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
dash.texi | 40 +++++++++++++++++++++++++++++++++++++
dev/examples.el | 23 ++++++++++++++++++++-
4 files changed, 159 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 164b7c1..584fcf7 100644
--- a/README.md
+++ b/README.md
@@ -1915,6 +1915,46 @@ plist-like key-value pairs, similarly to &keys keyword of
This binds `n` values from the list to a1 ... aN, then interprets
the cdr as a plist (see key/value matching above).
+You can name the source using the syntax `symbol` &as `pattern`.
+This syntax works with lists (proper or improper), vectors and
+all types of maps.
+
+ (list &as a b c) (list 1 2 3)
+
+binds `a` to 1, `b` to 2, `c` to 3 and `list` to (1 2 3).
+
+Similarly:
+
+ (bounds &as beg . end) (cons 1 2)
+
+binds `beg` to 1, `end` to 2 and `bounds` to (1 . 2).
+
+ (items &as first . rest) (list 1 2 3)
+
+binds `first` to 1, `rest` to (2 3) and `items` to (1 2 3)
+
+ [vect &as _ b c] [1 2 3]
+
+binds `b` to 2, `c` to 3 and `vect` to [1 2 3] (_ avoids binding as usual).
+
+ (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+binds `b` to 2 and `plist` to (:a 1 :b 2 :c 3). Same for &alist and &hash.
+
+This is especially useful when we want to capture the result of a
+computation and destructure at the same time. Consider the
+form (function-returning-complex-structure) returning a list of
+two vectors with two items each. We want to capture this entire
+result and pass it to another computation, but at the same time
+we want to get the second item from each vector. We can achieve
+it with pattern
+
+ (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+Note: Clojure programmers may know this feature as the ":as
+binding". The difference is that we put the &as at the front
+because we need to support improper list binding.
+
```el
(-let (([a (b c) d] [1 (2 3) 4])) (list a b c d)) ;; => '(1 2 3 4)
(-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d)) ;; => '(1 2 3 (4 5 6))
diff --git a/dash.el b/dash.el
index d2c2b4d..2c96cf9 100644
--- a/dash.el
+++ b/dash.el
@@ -1452,13 +1452,28 @@ Key-value stores are disambiguated by placing a token
&plist,
(dash--match-symbol match-form source))
((consp match-form)
(cond
+ ;; Handle the "x &as" bindings first.
+ ((and (consp (cdr match-form))
+ (symbolp (car match-form))
+ (eq '&as (cadr match-form)))
+ (let ((s (car match-form)))
+ (cons (list s source)
+ (dash--match (cddr match-form) s))))
((memq (car match-form) '(&plist &alist &hash))
(dash--match-kv match-form source))
((eq (car match-form) '&keys)
(dash--match-kv (cons '&plist (cdr match-form)) source))
(t (dash--match-cons match-form source))))
((vectorp match-form)
- (dash--match-vector match-form source))))
+ ;; We support the &as binding in vectors too
+ (cond
+ ((and (> (length match-form) 2)
+ (symbolp (aref match-form 0))
+ (eq '&as (aref match-form 1)))
+ (let ((s (aref match-form 0)))
+ (cons (list s source)
+ (dash--match (dash--vector-tail match-form 2) s))))
+ (t (dash--match-vector match-form source))))))
(defmacro -let* (varlist &rest body)
"Bind variables according to VARLIST then eval BODY.
@@ -1565,7 +1580,47 @@ plist-like key-value pairs, similarly to &keys keyword of
(a1 a2 ... aN &keys key1 b1 ... keyN bK)
This binds N values from the list to a1 ... aN, then interprets
-the cdr as a plist (see key/value matching above)."
+the cdr as a plist (see key/value matching above).
+
+You can name the source using the syntax SYMBOL &as PATTERN.
+This syntax works with lists (proper or improper), vectors and
+all types of maps.
+
+ (list &as a b c) (list 1 2 3)
+
+binds A to 1, B to 2, C to 3 and LIST to (1 2 3).
+
+Similarly:
+
+ (bounds &as beg . end) (cons 1 2)
+
+binds BEG to 1, END to 2 and BOUNDS to (1 . 2).
+
+ (items &as first . rest) (list 1 2 3)
+
+binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3)
+
+ [vect &as _ b c] [1 2 3]
+
+binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as usual).
+
+ (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and &hash.
+
+This is especially useful when we want to capture the result of a
+computation and destructure at the same time. Consider the
+form (function-returning-complex-structure) returning a list of
+two vectors with two items each. We want to capture this entire
+result and pass it to another computation, but at the same time
+we want to get the second item from each vector. We can achieve
+it with pattern
+
+ (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+Note: Clojure programmers may know this feature as the \":as
+binding\". The difference is that we put the &as at the front
+because we need to support improper list binding."
(declare (debug ([&or (&rest (sexp form))
(vector [&rest [sexp form]])]
body))
diff --git a/dash.texi b/dash.texi
index a6f5a1d..67bfee1 100644
--- a/dash.texi
+++ b/dash.texi
@@ -2931,6 +2931,46 @@ plist-like key-value pairs, similarly to &keys keyword of
This binds @var{n} values from the list to a1 ... aN, then interprets
the cdr as a plist (see key/value matching above).
+You can name the source using the syntax @var{symbol} &as @var{pattern}.
+This syntax works with lists (proper or improper), vectors and
+all types of maps.
+
+ (list &as a b c) (list 1 2 3)
+
+binds @var{a} to 1, @var{b} to 2, @var{c} to 3 and @var{list} to (1 2 3).
+
+Similarly:
+
+ (bounds &as beg . end) (cons 1 2)
+
+binds @var{beg} to 1, @var{end} to 2 and @var{bounds} to (1 . 2).
+
+ (items &as first . rest) (list 1 2 3)
+
+binds @var{first} to 1, @var{rest} to (2 3) and @var{items} to (1 2 3)
+
+ [vect &as _ b c] [1 2 3]
+
+binds @var{b} to 2, @var{c} to 3 and @var{vect} to [1 2 3] (_ avoids binding
as usual).
+
+ (plist &as &plist :b b) (list :a 1 :b 2 :c 3)
+
+binds @var{b} to 2 and @var{plist} to (:a 1 :b 2 :c 3). Same for &alist and
&hash.
+
+This is especially useful when we want to capture the result of a
+computation and destructure at the same time. Consider the
+form (function-returning-complex-structure) returning a list of
+two vectors with two items each. We want to capture this entire
+result and pass it to another computation, but at the same time
+we want to get the second item from each vector. We can achieve
+it with pattern
+
+ (result &as [_ a] [_ b]) (function-returning-complex-structure)
+
+Note: Clojure programmers may know this feature as the ":as
+binding". The difference is that we put the &as at the front
+because we need to support improper list binding.
+
@example
@group
(-let (([a (b c) d] [1 (2 3) 4])) (list a b c d))
diff --git a/dev/examples.el b/dev/examples.el
index b32d5c5..21e8ba5 100644
--- a/dev/examples.el
+++ b/dev/examples.el
@@ -791,10 +791,12 @@ new list."
(-let [[a b c] "abcdef"] (list a b c)) => '(?a ?b ?c)
(-let [[a (b [c]) d] [1 (2 [3 4]) 5 6]] (list a b c d)) => '(1 2 3 5)
(-let [(a b c d) (list 1 2 3 4 5 6)] (list a b c d)) => '(1 2 3 4)
+ (-let [([a b]) (list (vector 1 2 3))] (list a b)) => '(1 2)
;; d is bound to nil. I don't think we want to error in such a case.
;; After all (car nil) => nil
(-let [(a b c d) (list 1 2 3)] (list a b c d)) => '(1 2 3 nil)
(-let [[a b c] [1 2 3 4]] (list a b c)) => '(1 2 3)
+ (-let [[a] [1 2 3 4]] a) => 1
(-let [[a b &rest c] "abcdef"] (list a b c)) => '(?a ?b "cdef")
(-let [[a b &rest c] [1 2 3 4 5 6]] (list a b c)) => '(1 2 [3 4 5 6])
(-let [[a b &rest [c d]] [1 2 3 4 5 6]] (list a b c d)) => '(1 2 3 4)
@@ -872,7 +874,26 @@ new list."
(-let [[(a _ b)] (vector (list 1 2 3 4))] (list a b)) => '(1 3)
(-let [(&plist 'a a) (list 'a 1 'b 2)] a) => 1
(-let [(&plist 'a [a b]) (list 'a [1 2] 'b 3)] (list a b)) => '(1 2)
- (-let [(&plist 'a [a b] 'c c) (list 'a [1 2] 'c 3)] (list a b c)) => '(1 2
3))
+ (-let [(&plist 'a [a b] 'c c) (list 'a [1 2] 'c 3)] (list a b c)) => '(1 2
3)
+ ;; test the &as form
+ (-let (((items &as first . rest) (list 1 2 3))) (list first rest items))
=> '(1 (2 3) (1 2 3))
+ (-let [(all &as [vect &as a b] bar) (list [1 2] 3)] (list a b bar vect
all)) => '(1 2 3 [1 2] ([1 2] 3))
+ (-let [(all &as (list &as a b) bar) (list (list 1 2) 3)] (list a b bar
list all)) => '(1 2 3 (1 2) ((1 2) 3))
+ (-let [(x &as [a b]) (list (vector 1 2 3))] (list a b x)) => '(1 2 ([1 2
3]))
+ (-let [(result &as [_ a] [_ b]) (list [1 2] [3 4])] (list a b result)) =>
'(2 4 ([1 2] [3 4]))
+ (-let [(result &as [fst &as _ a] [snd &as _ b]) (list [1 2] [3 4])] (list
a b fst snd result)) => '(2 4 [1 2] [3 4] ([1 2] [3 4]))
+ (-let [[x &as a b &rest r] (vector 1 2 3)] (list a b r x)) => '(1 2 [3] [1
2 3])
+ (-let [[x &as a] (vector 1 2 3)] (list a x)) => '(1 [1 2 3])
+ (-let [[x &as _ _ a] (vector 1 2 3)] (list a x)) => '(3 [1 2 3])
+ (-let [[x &as _ _ a] (vector 1 2 (list 3 4))] (list a x)) => '((3 4) [1 2
(3 4)])
+ (-let [[x &as _ _ (a b)] (vector 1 2 (list 3 4))] (list a b x)) => '(3 4
[1 2 (3 4)])
+ (-let [(b &as beg . end) (cons 1 2)] (list beg end b)) => '(1 2 (1 . 2))
+ (-let [(plist &as &plist :a a :b b) (list :a 1 :b 2)] (list a b plist)) =>
'(1 2 (:a 1 :b 2))
+ (-let [(alist &as &alist :a a :b b) (list (cons :a 1) (cons :b 2))] (list
a b alist)) => '(1 2 ((:a . 1) (:b . 2)))
+ (-let [(list &as _ _ _ a _ _ _ b _ _ _ c) (list 1 2 3 4 5 6 7 8 9 10 11
12)] (list a b c list)) => '(4 8 12 (1 2 3 4 5 6 7 8 9 10 11 12))
+ (-let (((x &as a b) (list 1 2))
+ ((y &as c d) (list 3 4)))
+ (list a b c d x y)) => '(1 2 3 4 (1 2) (3 4)))
(defexamples -let*
(-let* (((a . b) (cons 1 2))
- [elpa] externals/dash b88cfb7 436/439: Add dash prefix to epsilon variable., (continued)
- [elpa] externals/dash b88cfb7 436/439: Add dash prefix to epsilon variable., Phillip Lord, 2015/08/04
- [elpa] externals/dash eadb265 439/439: Swap examples to better show how -some-> works, Phillip Lord, 2015/08/04
- [elpa] externals/dash 2aeeacb 433/439: Release 2.11.0, Phillip Lord, 2015/08/04
- [elpa] externals/dash c3cf98d 438/439: Add `-some->`, `-some->>`, and `-some-->` macros., Phillip Lord, 2015/08/04
- [elpa] externals/dash 1c2f43d 434/439: Add "See also" for the reduce family, Phillip Lord, 2015/08/04
- [elpa] externals/dash 2b69c14 411/439: Add dash.info and dash.texi to repo, Phillip Lord, 2015/08/04
- [elpa] externals/dash e574465 404/439: Add `-some`, Phillip Lord, 2015/08/04
- [elpa] externals/dash 4640a2a 405/439: Allow for approx comparison of floats in tests, Phillip Lord, 2015/08/04
- [elpa] externals/dash 3b63476 412/439: Move anaphoric function intro up into Functions section, Phillip Lord, 2015/08/04
- [elpa] externals/dash 19fbc24 426/439: Fix anaphoric -spice-list macro, Phillip Lord, 2015/08/04
- [elpa] externals/dash 2db56f5 424/439: [-let] Add support for &as bindings (#115),
Phillip Lord <=
- [elpa] externals/dash ffa37bf 425/439: Merge pull request #129 from holomorph/docs, Phillip Lord, 2015/08/04
- [elpa] externals/dash 81b808d 409/439: Ignore dash.elc, Phillip Lord, 2015/08/04
- [elpa] externals/dash c61113b 420/439: [-let] Update outdated comment, Phillip Lord, 2015/08/04
- [elpa] externals/dash 733274f 398/439: Merge pull request #120 from holomorph/info-manual, Phillip Lord, 2015/08/04
- [elpa] externals/dash a803dd5 414/439: Merge readme changes, Phillip Lord, 2015/08/04
- [elpa] externals/dash 7bd6b3b 400/439: Add dir entry to texinfo template, Phillip Lord, 2015/08/04
- [elpa] externals/dash 5219ac0 422/439: [-let] Eliminate useless re-binding of symbols when sources are immutable, Phillip Lord, 2015/08/04
- [elpa] externals/dash 0ef7384 395/439: Merge pull request #114 from fbergroth/update-test-case, Phillip Lord, 2015/08/04
- [elpa] externals/dash 349931e 399/439: Add @holomorph to list of contributors, Phillip Lord, 2015/08/04
- [elpa] externals/dash 1d4881f 413/439: Update README, Phillip Lord, 2015/08/04