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

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

[elpa] externals/dash 8c4e27f 108/316: Implement -setq


From: ELPA Syncer
Subject: [elpa] externals/dash 8c4e27f 108/316: Implement -setq
Date: Mon, 15 Feb 2021 15:57:37 -0500 (EST)

branch: externals/dash
commit 8c4e27fa7e8d31cb60d62bc27a22e82408af0c8f
Author: Matus Goljer <matus.goljer@gmail.com>
Commit: Matus Goljer <matus.goljer@gmail.com>

    Implement -setq
---
 README.md       | 30 +++++++++++++++++++
 dash.el         | 54 ++++++++++++++++++++++++++++++++++
 dash.info       | 91 +++++++++++++++++++++++++++++++++++++--------------------
 dash.texi       | 39 +++++++++++++++++++++++++
 dev/examples.el | 12 +++++++-
 5 files changed, 194 insertions(+), 32 deletions(-)

diff --git a/README.md b/README.md
index 3c9d006..7fa86c1 100644
--- a/README.md
+++ b/README.md
@@ -288,6 +288,7 @@ Convenient versions of `let` and `let*` constructs combined 
with flow control.
 * [-let](#-let-varlist-rest-body) `(varlist &rest body)`
 * [-let*](#-let-varlist-rest-body) `(varlist &rest body)`
 * [-lambda](#-lambda-match-form-rest-body) `(match-form &rest body)`
+* [-setq](#-setq-rest-forms) `(&rest forms)`
 
 ### Side-effects
 
@@ -2429,6 +2430,35 @@ See [`-let`](#-let-varlist-rest-body) for the 
description of destructuring mecha
 (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6)) ;; => 
'(2 3 5 6)
 ```
 
+#### -setq `(&rest forms)`
+
+Bind each `match-form` to the value of its `val`.
+
+`match-form` destructuring is done according to the rules of 
[`-let`](#-let-varlist-rest-body).
+
+This macro allows you to bind multiple variables by destructuring
+the value, so for example:
+
+    (-setq (a b) x
+           (&plist :c c) plist)
+
+expands roughly speaking to the following code
+
+    (setq a (car x)
+          b (cadr x)
+          c (plist-get plist :c))
+
+Care is taken to only evaluate each `val` once so that in case of
+multiple assignments it does not cause unexpected side effects.
+
+(fn [`match-form` `val`]...)
+
+```el
+(progn (-setq a 1) a) ;; => 1
+(progn (-setq (a b) (list 1 2)) (list a b)) ;; => '(1 2)
+(progn (-setq (&plist :c c) (list :c "c")) c) ;; => "c"
+```
+
 
 ## Side-effects
 
diff --git a/dash.el b/dash.el
index 89c01b5..a115a43 100644
--- a/dash.el
+++ b/dash.el
@@ -1978,6 +1978,60 @@ See `-let' for the description of destructuring 
mechanism."
       `(lambda ,(--map (cadr it) inputs)
          (-let* ,inputs ,@body))))))
 
+(defmacro -setq (&rest forms)
+  "Bind each MATCH-FORM to the value of its VAL.
+
+MATCH-FORM destructuring is done according to the rules of `-let'.
+
+This macro allows you to bind multiple variables by destructuring
+the value, so for example:
+
+  (-setq (a b) x
+         (&plist :c c) plist)
+
+expands roughly speaking to the following code
+
+  (setq a (car x)
+        b (cadr x)
+        c (plist-get plist :c))
+
+Care is taken to only evaluate each VAL once so that in case of
+multiple assignments it does not cause unexpected side effects.
+
+(fn [MATCH-FORM VAL]...)"
+  (declare (debug (&rest sexp form))
+           (indent 1))
+  (when (= (mod (length forms) 2) 1)
+    (error "Odd number of arguments"))
+  (let* ((forms-and-sources
+          ;; First get all the necessary mappings with all the
+          ;; intermediate bindings.
+          (-map (lambda (x) (dash--match (car x) (cadr x)))
+                (-partition 2 forms)))
+         ;; To preserve the logic of dynamic scoping we must ensure
+         ;; that we `setq' the variables outside of the `let*' form
+         ;; which holds the destructured intermediate values.  For
+         ;; this we generate for each variable a placeholder which is
+         ;; bound to (lexically) the result of the destructuring.
+         ;; Then outside of the helper `let*' form we bind all the
+         ;; original variables to their respective placeholders.
+         ;; TODO: There is a lot of room for possible optimization,
+         ;; for start playing with `special-variable-p' to eliminate
+         ;; unnecessary re-binding.
+         (variables-to-placeholders
+          (-mapcat
+           (lambda (bindings)
+             (-map
+              (lambda (binding)
+                (let ((var (car binding)))
+                  (list var (make-symbol (concat "--dash-binding-" 
(symbol-name var) "--")))))
+              (--filter (not (string-prefix-p "--" (symbol-name (car it)))) 
bindings)))
+           forms-and-sources)))
+    `(let ,(-map 'cadr variables-to-placeholders)
+       (let* ,(-flatten-n 1 forms-and-sources)
+         (setq ,@(-flatten (-map 'reverse variables-to-placeholders))))
+       (setq ,@(-flatten variables-to-placeholders)))))
+
 (defmacro -if-let* (vars-vals then &rest else)
   "If all VALS evaluate to true, bind them to their corresponding
 VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list
diff --git a/dash.info b/dash.info
index 3116c4b..5d10cc8 100644
--- a/dash.info
+++ b/dash.info
@@ -1,4 +1,4 @@
-This is dash.info, produced by makeinfo version 6.5 from dash.texi.
+This is dash.info, produced by makeinfo version 6.1 from dash.texi.
 
 This manual is for ‘dash.el’ version 2.12.1.
 
@@ -2354,6 +2354,33 @@ control.
           (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6))
               ⇒ '(2 3 5 6)
 
+ -- Macro: -setq (&rest forms)
+     Bind each MATCH-FORM to the value of its VAL.
+
+     MATCH-FORM destructuring is done according to the rules of ‘-let’
+     (*note -let::).
+
+     This macro allows you to bind multiple variables by destructuring
+     the value, so for example:
+
+     (-setq (a b) x (&plist :c c) plist)
+
+     expands roughly speaking to the following code
+
+     (setq a (car x) b (cadr x) c (plist-get plist :c))
+
+     Care is taken to only evaluate each VAL once so that in case of
+     multiple assignments it does not cause unexpected side effects.
+
+     (fn [MATCH-FORM VAL]...)
+
+          (progn (-setq a 1) a)
+              ⇒ 1
+          (progn (-setq (a b) (list 1 2)) (list a b))
+              ⇒ '(1 2)
+          (progn (-setq (&plist :c c) (list :c "c")) c)
+              ⇒ "c"
+
 
 File: dash.info,  Node: Side-effects,  Next: Destructive operations,  Prev: 
Binding,  Up: Functions
 
@@ -3029,6 +3056,7 @@ Index
 * -select-column:                        Sublist selection. (line 199)
 * -select-columns:                       Sublist selection. (line 180)
 * -separate:                             Partitioning.      (line  63)
+* -setq:                                 Binding.           (line 243)
 * -slice:                                Sublist selection. (line  86)
 * -snoc:                                 Other list operations.
                                                             (line  42)
@@ -3245,36 +3273,37 @@ Ref: -if-let*72745
 Ref: -let73362
 Ref: -let*78155
 Ref: -lambda79096
-Node: Side-effects79898
-Ref: -each80092
-Ref: -each-while80499
-Ref: -each-indexed80859
-Ref: -dotimes81377
-Ref: -doto81680
-Node: Destructive operations82107
-Ref: !cons82280
-Ref: !cdr82486
-Node: Function combinators82681
-Ref: -partial82955
-Ref: -rpartial83350
-Ref: -juxt83752
-Ref: -compose84184
-Ref: -applify84742
-Ref: -on85189
-Ref: -flip85712
-Ref: -const86024
-Ref: -cut86368
-Ref: -not86854
-Ref: -orfn87164
-Ref: -andfn87598
-Ref: -iteratefn88093
-Ref: -fixfn88796
-Ref: -prodfn90365
-Node: Development91431
-Node: Contribute91780
-Node: Changes92528
-Node: Contributors95527
-Node: Index97151
+Ref: -setq79898
+Node: Side-effects80714
+Ref: -each80908
+Ref: -each-while81315
+Ref: -each-indexed81675
+Ref: -dotimes82193
+Ref: -doto82496
+Node: Destructive operations82923
+Ref: !cons83096
+Ref: !cdr83302
+Node: Function combinators83497
+Ref: -partial83771
+Ref: -rpartial84166
+Ref: -juxt84568
+Ref: -compose85000
+Ref: -applify85558
+Ref: -on86005
+Ref: -flip86528
+Ref: -const86840
+Ref: -cut87184
+Ref: -not87670
+Ref: -orfn87980
+Ref: -andfn88414
+Ref: -iteratefn88909
+Ref: -fixfn89612
+Ref: -prodfn91181
+Node: Development92247
+Node: Contribute92596
+Node: Changes93344
+Node: Contributors96343
+Node: Index97967
 
 End Tag Table
 
diff --git a/dash.texi b/dash.texi
index e6a1ffb..4fb616d 100644
--- a/dash.texi
+++ b/dash.texi
@@ -3700,6 +3700,45 @@ See @code{-let} (@pxref{-let}) for the description of 
destructuring mechanism.
 @end example
 @end defmac
 
+@anchor{-setq}
+@defmac -setq (&rest forms)
+Bind each @var{match-form} to the value of its @var{val}.
+
+@var{match-form} destructuring is done according to the rules of @code{-let} 
(@pxref{-let}).
+
+This macro allows you to bind multiple variables by destructuring
+the value, so for example:
+
+    (-setq (a b) x
+           (&plist :c c) plist)
+
+expands roughly speaking to the following code
+
+    (setq a (car x)
+          b (cadr x)
+          c (plist-get plist :c))
+
+Care is taken to only evaluate each @var{val} once so that in case of
+multiple assignments it does not cause unexpected side effects.
+
+(fn [@var{match-form} @var{val}]...)
+
+@example
+@group
+(progn (-setq a 1) a)
+    @result{} 1
+@end group
+@group
+(progn (-setq (a b) (list 1 2)) (list a b))
+    @result{} '(1 2)
+@end group
+@group
+(progn (-setq (&plist :c c) (list :c "c")) c)
+    @result{} "c"
+@end group
+@end example
+@end defmac
+
 
 @node Side-effects
 @section Side-effects
diff --git a/dev/examples.el b/dev/examples.el
index 37c1fd9..bd35559 100644
--- a/dev/examples.el
+++ b/dev/examples.el
@@ -1146,7 +1146,17 @@ new list."
     (funcall (-lambda ((a) (b)) (+ a b)) '(1 2 3) '(4 5 6)) => 5
     (-lambda a t) !!> wrong-type-argument
     (funcall (-lambda (a b) (+ a b)) 1 2) => 3
-    (funcall (-lambda (a (b c)) (+ a b c)) 1 (list 2 3)) => 6))
+    (funcall (-lambda (a (b c)) (+ a b c)) 1 (list 2 3)) => 6)
+
+  (defexamples -setq
+    (progn (-setq a 1) a) => 1
+    (progn (-setq (a b) (list 1 2)) (list a b)) => '(1 2)
+    (progn (-setq (&plist :c c) (list :c "c")) c) => "c"
+    (progn (-setq a 1 b 2) (list a b)) => '(1 2)
+    (progn (-setq (&plist :a a) (list :a (list :b 1))
+                  (&plist :b b) a) b) => 1
+    (-setq (a b (&plist 'x x 'y y)) (list 1 2 (list 'x 3 'y 4))
+           z x) => 3))
 
 (def-example-group "Side-effects"
   "Functions iterating over lists for side-effect only."



reply via email to

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