# HG changeset patch # User Steve Losh # Date 1471294787 0 # Node ID b0292af3444e6f14f6b7f05a7c160e72bfdf244a # Parent 5ef5b5b223edd12e8f91cf6f7811da74d9badbde Add more mutation functions diff -r 5ef5b5b223ed -r b0292af3444e losh.lisp --- 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 diff -r 5ef5b5b223ed -r b0292af3444e package.lisp --- 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