Merge pull request #921 from hellerve/veit/doto

Add doto and doto-ref
This commit is contained in:
Erik Svedäng 2020-08-26 20:58:12 +02:00 committed by GitHub
commit 87a49f66ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 0 deletions

View File

@ -777,3 +777,46 @@ the program will be aborted with an error message.")
msg)))
(list 'System.abort)
(list 'bottom)))
(doc doto "evaluates `thing`, then calls all of the functions on it and
returns it. Useful for chaining mutating, imperative functions, and thus
similar to `->`. If you need `thing` to be passed as a `ref` into `expressions`
functions, use [`doto-ref`](#doto-ref) instead.
Example:
```
(let [x @\"hi\"]
@(doto &x
(string-set! 0 \o)
(string-set! 1 \y)))
```
")
(defmacro doto [thing :rest expressions]
(let [s (gensym)]
(list 'let [s thing]
(cons-last
s
(cons 'do (map (fn [expr] (cons (car expr) (cons s (cdr expr)))) expressions))))))
(doc doto-ref "evaluates `thing`, then calls all of the functions on it and
returns it. Useful for chaining mutating, imperative functions, and thus
similar to `->`. If you need `thing` not to be passed as a `ref` into
`expressions` functions, use [`doto`](#doto) instead.
Example:
```
(doto-ref @\"hi\"
(string-set! 0 \o)
(string-set! 1 \y))
```
")
(defmacro doto-ref [thing :rest expressions]
(let [s (gensym)]
(list 'let [s thing]
(cons-last
s
(cons 'do
(map (fn [expr] (cons (car expr) (cons (list 'ref s) (cdr expr))))
expressions))))))

View File

@ -309,4 +309,17 @@
(assert-true test
(test-dynamic-while)
"while works as expected in dynamic code")
(assert-ref-equal test
@"oy"
(let [x @"hi"]
@(doto &x
(string-set! 0 \o)
(string-set! 1 \y)))
"doto works as expected")
(assert-ref-equal test
@"oy"
(doto-ref @"hi"
(string-set! 0 \o)
(string-set! 1 \y))
"doto-ref works as expected")
)