b0292af3444e

Add more mutation functions
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Mon, 15 Aug 2016 20:59:47 +0000
parents 5ef5b5b223ed
children cf3fce2172bc
branches/tags (none)
files losh.lisp package.lisp

Changes

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