[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/dash 947ffda 341/426: Add support for &rest match for n
From: |
Phillip Lord |
Subject: |
[elpa] externals/dash 947ffda 341/426: Add support for &rest match for non-list sequences (like . for improper lists) |
Date: |
Tue, 04 Aug 2015 19:38:44 +0000 |
branch: externals/dash
commit 947ffdaa1ae0eb0c72c6a0bc6d5467fde9bc7122
Author: Matus Goljer <address@hidden>
Commit: Matus Goljer <address@hidden>
Add support for &rest match for non-list sequences (like . for improper
lists)
---
README.md | 5 ++++
dash.el | 60 ++++++++++++++++++++++++++++++++++++++++++------------
dev/examples.el | 7 +++++-
3 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index 5b425ac..a2f3bf0 100644
--- a/README.md
+++ b/README.md
@@ -1763,6 +1763,11 @@ Vectors:
If the `pattern` is longer than `source`, an `error` is
thrown.
+ [a1 a2 a3 ... &rest rest] ) - as above, but bind the rest of
+ the sequence to `rest`. This is
+ conceptually the same as improper list
+ matching (a1 a2 ... aN . rest)
+
Key/value stores:
(&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
diff --git a/dash.el b/dash.el
index 7efe2b7..de2122e 100644
--- a/dash.el
+++ b/dash.el
@@ -1208,9 +1208,17 @@ SOURCE is a proper or improper list."
(t
(list (list match-form s)))))
-;; TODO: add support to match the "rest" of the sequence, so that we
-;; can break apart strings for example
-;; (-let (([h &rest tail] "fobar")) (list h tail)) => (102 "obar")
+(defun dash--vector-tail (seq start)
+ "Return the tail of SEQ starting at START."
+ (cond
+ ((vectorp seq)
+ (let* ((re-length (- (length seq) start))
+ (re (make-vector re-length 0)))
+ (--dotimes re-length (aset re it (aref seq (+ it start))))
+ re))
+ ((stringp seq)
+ (substring seq start))))
+
(defun dash--match-vector (match-form source)
"Setup a vector matching environment and call the real matcher."
(let ((s (make-symbol "--dash-source--")))
@@ -1223,22 +1231,41 @@ MATCH-FORM is a vector. Each element of MATCH-FORM is
either a
symbol, which gets bound to the respective value in source or
another match form which gets destructured recursively.
+If second-from-last place in MATCH-FORM is the symbol &rest, the
+next element of the MATCH-FORM is matched against the tail of
+SOURCE, starting at index of the &rest symbol. This is
+conceptually the same as the (head . tail) match for improper
+lists, where dot plays the role of &rest.
+
SOURCE is a vector.
If the MATCH-FORM vector is shorter than SOURCE vector, only
the (length MATCH-FORM) places are bound, the rest of the SOURCE
is discarded."
- (let ((i 0))
- (-flatten-n 1 (--map
- (let ((m (aref match-form i)))
- (prog1 (cond
- ((and (symbolp m)
- ;; do not match symbols starting with _
- (not (eq (aref (symbol-name m) 0) ?_)))
- (list (list m `(aref ,source ,i))))
- (t (dash--match m `(aref ,source ,i))))
- (setq i (1+ i))))
- match-form))))
+ (let ((i 0)
+ (l (length match-form))
+ (re))
+ (while (< i l)
+ (let ((m (aref match-form i)))
+ (push (cond
+ ((and (symbolp m)
+ (eq m '&rest))
+ ;; the reversing here is necessary, because we reverse
+ ;; `re' in the end. That would then incorrectly
+ ;; reorder sub-expression matches
+ (prog1 (nreverse
+ (dash--match
+ (aref match-form (1+ i))
+ `(dash--vector-tail ,source ,i)))
+ (setq i l)))
+ ((and (symbolp m)
+ ;; do not match symbols starting with _
+ (not (eq (aref (symbol-name m) 0) ?_)))
+ (list (list m `(aref ,source ,i))))
+ (t (nreverse (dash--match m `(aref ,source ,i)))))
+ re)
+ (setq i (1+ i))))
+ (nreverse (-flatten-n 1 re))))
(defun dash--match-kv (match-form source)
"Setup a kv matching environment and call the real matcher.
@@ -1381,6 +1408,11 @@ Vectors:
If the PATTERN is longer than SOURCE, an `error' is
thrown.
+ [a1 a2 a3 ... &rest rest] ) - as above, but bind the rest of
+ the sequence to REST. This is
+ conceptually the same as improper list
+ matching (a1 a2 ... aN . rest)
+
Key/value stores:
(&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the
diff --git a/dev/examples.el b/dev/examples.el
index d78bccc..55f3572 100644
--- a/dev/examples.el
+++ b/dev/examples.el
@@ -720,14 +720,19 @@ new list."
(list bar face inv)) => '(2 foo-face t)
(-let [(a (b c) d) (list 1 (list 2 3) 4 5 6)] (list a b c d)) => '(1 2 3 4)
(-let [[a _ c] [1 2 3 4]] (list a c)) => '(1 3)
+ (-let [[a (b c) d] [1 (2 3) 4]] (list a b c d)) => '(1 2 3 4)
(-let [[a b c] (string ?f ?o ?b ?a ?r)] (list a b c)) => '(?f ?o ?b)
+ (-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)
;; 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)
- ;; here we error, because "vectors" are rigit, immutable structures,
+ (-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)
+ ;; here we error, because "vectors" are rigid, immutable structures,
;; so we should know how many elements there are
(condition-case nil
(-let [[a b c d] [1 2 3]]
- [elpa] externals/dash ab99be6 335/426: Add -fix, (continued)
- [elpa] externals/dash ab99be6 335/426: Add -fix, Phillip Lord, 2015/08/04
- [elpa] externals/dash b1e585d 337/426: Update copyright notice, Phillip Lord, 2015/08/04
- [elpa] externals/dash 3adad97 334/426: Add -non-nil, Phillip Lord, 2015/08/04
- [elpa] externals/dash 166bccd 333/426: Add -tree-map-nodes, Phillip Lord, 2015/08/04
- [elpa] externals/dash 05fa92f 342/426: [-let] Transpose nreverse/flatten, Phillip Lord, 2015/08/04
- [elpa] externals/dash f0831d3 339/426: Add -lambda, Phillip Lord, 2015/08/04
- [elpa] externals/dash 9ebcce6 325/426: Add some niceties to font-locking of examples, Phillip Lord, 2015/08/04
- [elpa] externals/dash 6fc652d 331/426: Merge pull request #95 from Wilfred/shallow-copy-function, Phillip Lord, 2015/08/04
- [elpa] externals/dash 5637bd6 322/426: Add alias from -find to -first, Phillip Lord, 2015/08/04
- [elpa] externals/dash a4be872 338/426: Add `-let` and `-let*`, Phillip Lord, 2015/08/04
- [elpa] externals/dash 947ffda 341/426: Add support for &rest match for non-list sequences (like . for improper lists),
Phillip Lord <=
- [elpa] externals/dash 9065e1b 344/426: [-let] Final cdr shift optimization, Phillip Lord, 2015/08/04
- [elpa] externals/dash d37947a 332/426: Add -tree-seq, Phillip Lord, 2015/08/04
- [elpa] externals/dash 51a0c9f 350/426: [-let] Fix expansion of _ symbols in vector matcher, Phillip Lord, 2015/08/04
- [elpa] externals/dash 8f9fc41 340/426: Add support for multiple input arguments to -lambda, Phillip Lord, 2015/08/04
- [elpa] externals/dash 7f2b3c7 343/426: [-lambda] test all match-forms before converting to regular lambda, Phillip Lord, 2015/08/04
- [elpa] externals/dash 6f81492 346/426: [-lambda] Better error-handling, Phillip Lord, 2015/08/04
- [elpa] externals/dash 6f0bb7d 348/426: [-let] Fix dynamic scoping issue, Phillip Lord, 2015/08/04
- [elpa] externals/dash f939201 347/426: [-let] Optimize shifting/binding of unused _ places, Phillip Lord, 2015/08/04
- [elpa] externals/dash c1d555b 355/426: [-let] Optimize single-binding of vectors and kv, Phillip Lord, 2015/08/04
- [elpa] externals/dash edb1e31 356/426: [-let] Add more tests, Phillip Lord, 2015/08/04