--- a/losh.lisp Mon Aug 15 05:43:54 2016 +0000
+++ b/losh.lisp Mon Aug 15 20:59:47 2016 +0000
@@ -244,7 +244,7 @@
;;;; Mutation
-(defun build-zap% (place expr env)
+(defun build-zap (place expr env)
(multiple-value-bind (temps exprs stores store-expr access-expr)
(get-setf-expansion place env)
`(let* (,@(mapcar #'list temps exprs)
@@ -252,36 +252,68 @@
,expr)))
,store-expr)))
-(defmacro zap% (&rest place-expr-pairs &environment env)
+(defmacro zapf (&rest place-expr-pairs &environment env)
"Update each `place` by evaluating `expr` with `%` bound to the current value.
- `zap%` works like `setf`, but when evaluating the value expressions the symbol
- `%` will be `symbol-macrolet`ed to the current value of the place.
+ `zapf` works like `setf`, but when evaluating the value expressions the symbol
+ `%` will be bound to the current value of the place.
Examples:
- (zap% foo (1+ %)
+ (zapf foo (1+ %)
(car bar) (if (> % 10) :a :b))
"
;; original idea/name from http://malisper.me/2015/09/29/zap/
`(progn
,@(loop :for (place expr . rest) :on place-expr-pairs :by #'cddr
- :collect (build-zap% place expr env))))
+ :collect (build-zap place expr env))))
+
+
+(define-modify-macro mulf (factor) *
+ "Multiply `place` by `factor` in-place.")
-(defmacro zapf (&rest args)
- "Zap each place with each function."
- `(progn
- ,@(iterate (for (place function) :on args :by #'cddr)
- (collect `(zap% ,place (funcall ,function %))))))
+(define-modify-macro divf (&optional divisor)
+ (lambda (value divisor)
+ (if divisor
+ (/ value divisor)
+ (/ value)))
+ "Divide `place` by `divisor` in-place.
+
+ If `divisor` is not given, `place` will be set to `(/ 1 place).
+
+ ")
+
+(define-modify-macro modf (divisor) mod
+ "Modulo `place` by `divisor` in-place.")
+
+(define-modify-macro remainderf (divisor) rem
+ "Remainder `place` by `divisor` in-place.")
-(defmacro mulf (place n)
- "Multiply `place` by `n` in-place."
- `(zap% ,place (* % ,n)))
+(define-modify-macro clampf (from to) clamp
+ "Clamp `place` between `from` and `to` in-place.")
+
+
+(define-modify-macro %callf (function)
+ (lambda (value function)
+ (funcall function value))
+ "Set `place` to the result of calling `function` on its current value.")
+
+(defmacro callf (&rest place-function-pairs)
+ "Set each `place` to the result of calling `function` on its current value.
-(defmacro clampf (place from to)
- "Clamp `place` between `from` and `to` in-place."
- `(zap% ,place (clamp ,from ,to %)))
+ Examples:
+
+ (let ((x 10) (y 20))
+ (callf x #'1-
+ y #'1+)
+ (list x y))
+ =>
+ (9 21)
+ "
+ `(progn
+ ,@(loop :for (place function . rest) :on place-function-pairs :by #'cddr
+ :collect `(%callf ,place ,function))))
;;;; Lists
--- a/package.lisp Mon Aug 15 05:43:54 2016 +0000
+++ b/package.lisp Mon Aug 15 20:59:47 2016 +0000
@@ -29,11 +29,14 @@
#:recursively
#:recur
- #:zap%
+ #:zapf
#:%
- #:zapf
#:mulf
+ #:divf
+ #:modf
+ #:remainderf
#:clampf
+ #:callf
#:take