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)`
* [-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

@ -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

@ -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

@ -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

@ -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."

Loading…
Cancel
Save