Implement -setq

master
Matus Goljer 8 years ago
parent a55452a384
commit 8c4e27fa7e
  1. 30
      README.md
  2. 54
      dash.el
  3. 91
      dash.info
  4. 39
      dash.texi
  5. 12
      dev/examples.el

@ -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)`
* [-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)` * [-lambda](#-lambda-match-form-rest-body) `(match-form &rest body)`
* [-setq](#-setq-rest-forms) `(&rest forms)`
### Side-effects ### 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) (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 ## Side-effects

@ -1978,6 +1978,60 @@ See `-let' for the description of destructuring mechanism."
`(lambda ,(--map (cadr it) inputs) `(lambda ,(--map (cadr it) inputs)
(-let* ,inputs ,@body)))))) (-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) (defmacro -if-let* (vars-vals then &rest else)
"If all VALS evaluate to true, bind them to their corresponding "If all VALS evaluate to true, bind them to their corresponding
VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list

@ -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. 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)) (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6))
⇒ '(2 3 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 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-column: Sublist selection. (line 199)
* -select-columns: Sublist selection. (line 180) * -select-columns: Sublist selection. (line 180)
* -separate: Partitioning. (line 63) * -separate: Partitioning. (line 63)
* -setq: Binding. (line 243)
* -slice: Sublist selection. (line 86) * -slice: Sublist selection. (line 86)
* -snoc: Other list operations. * -snoc: Other list operations.
(line 42) (line 42)
@ -3245,36 +3273,37 @@ Ref: -if-let*72745
Ref: -let73362 Ref: -let73362
Ref: -let*78155 Ref: -let*78155
Ref: -lambda79096 Ref: -lambda79096
Node: Side-effects79898 Ref: -setq79898
Ref: -each80092 Node: Side-effects80714
Ref: -each-while80499 Ref: -each80908
Ref: -each-indexed80859 Ref: -each-while81315
Ref: -dotimes81377 Ref: -each-indexed81675
Ref: -doto81680 Ref: -dotimes82193
Node: Destructive operations82107 Ref: -doto82496
Ref: !cons82280 Node: Destructive operations82923
Ref: !cdr82486 Ref: !cons83096
Node: Function combinators82681 Ref: !cdr83302
Ref: -partial82955 Node: Function combinators83497
Ref: -rpartial83350 Ref: -partial83771
Ref: -juxt83752 Ref: -rpartial84166
Ref: -compose84184 Ref: -juxt84568
Ref: -applify84742 Ref: -compose85000
Ref: -on85189 Ref: -applify85558
Ref: -flip85712 Ref: -on86005
Ref: -const86024 Ref: -flip86528
Ref: -cut86368 Ref: -const86840
Ref: -not86854 Ref: -cut87184
Ref: -orfn87164 Ref: -not87670
Ref: -andfn87598 Ref: -orfn87980
Ref: -iteratefn88093 Ref: -andfn88414
Ref: -fixfn88796 Ref: -iteratefn88909
Ref: -prodfn90365 Ref: -fixfn89612
Node: Development91431 Ref: -prodfn91181
Node: Contribute91780 Node: Development92247
Node: Changes92528 Node: Contribute92596
Node: Contributors95527 Node: Changes93344
Node: Index97151 Node: Contributors96343
Node: Index97967
 
End Tag Table End Tag Table

@ -3700,6 +3700,45 @@ See @code{-let} (@pxref{-let}) for the description of destructuring mechanism.
@end example @end example
@end defmac @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 @node Side-effects
@section Side-effects @section Side-effects

@ -1146,7 +1146,17 @@ new list."
(funcall (-lambda ((a) (b)) (+ a b)) '(1 2 3) '(4 5 6)) => 5 (funcall (-lambda ((a) (b)) (+ a b)) '(1 2 3) '(4 5 6)) => 5
(-lambda a t) !!> wrong-type-argument (-lambda a t) !!> wrong-type-argument
(funcall (-lambda (a b) (+ a b)) 1 2) => 3 (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" (def-example-group "Side-effects"
"Functions iterating over lists for side-effect only." "Functions iterating over lists for side-effect only."

Loading…
Cancel
Save