emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/dash 2db56f5 424/426: [-let] Add support for &as bindin


From: Phillip Lord
Subject: [elpa] externals/dash 2db56f5 424/426: [-let] Add support for &as bindings (#115)
Date: Tue, 04 Aug 2015 19:39:22 +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))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]