aboutsummaryrefslogtreecommitdiffhomepage
path: root/gtwiwtg.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'gtwiwtg.lisp')
-rw-r--r--gtwiwtg.lisp61
1 files changed, 50 insertions, 11 deletions
diff --git a/gtwiwtg.lisp b/gtwiwtg.lisp
index 49b7d1b..67ee209 100644
--- a/gtwiwtg.lisp
+++ b/gtwiwtg.lisp
@@ -188,6 +188,8 @@ E.g.
If TO is NIL, then the generator produces an infinite series of
values.
"
+ :tests
+ :end
(let ((comparator (if (plusp by)
(if inclusive #'<= #'<)
(if inclusive #'>= #'>))))
@@ -761,23 +763,34 @@ Example: building data
(setf ,acc ,expr))
,acc))
-
-(defun collect (gen)
+(defun/t collect (gen)
"Consumes GEN by collecting its values into a list."
+ :tests
+ (:program test-collect)
+ :end
(nreverse (fold (xs nil) (x gen) (cons x xs))))
-(defun take (n gen)
+(defun/t take (n gen)
"Consumes GEN by collecting its first N values into a list"
+ :tests
+ (:program test-take)
+ :end
(nreverse (fold (xs nil) (x (zip! gen (times n)))
(cons (car x) xs))))
-(defun pick-out (indexes gen)
+(defun/t pick-out (indexes gen)
"Consumes GEN by picking out certain members by their index.
INDEXES is a list of non-negative integers.
Returns a list of values from GEN such that each value was an element
of indexes."
+ :tests
+ (:program test-pick-out)
+ (:fails (() (range))) ; index list cannot be null
+ (:fails ('(-10) (range))) ; indices cannot be negative
+ :end
+ (assert (notany #'minusp indexes))
(let ((acc (make-array (length indexes))))
(for (x idx) (zip! gen (times (1+ (apply #'max indexes))))
(when (member idx indexes)
@@ -788,22 +801,42 @@ of indexes."
:do (setf (aref acc i) x))))
(concatenate 'list acc)))
-(defun size (gen)
+(defun/t size (gen)
"Consumes GEN by calculating its size."
- (fold (n 0) (x gen) (1+ n)))
+ :tests
+ (= ((seq nil)) 0)
+ (= ((range :to 3)) 3)
+ :end
+ (fold (n 0) (x (map! (constantly 1) gen)) (+ n x)))
-(defun maximum (gen)
+(defun/t maximum (gen)
"Consumes GEN, returning its maximum value."
+ :tests
+ (= ((range :to 5)) 4)
+ (= ((range :to 5 :inclusive t)) 5)
+ (= ((range :from -10 :to 0 :by 3)) -1)
+ (:fails ((seq "hey")))
+ :end
(fold (m nil) (x gen)
(if m (max m x) x)))
-(defun minimum (gen)
+(defun/t minimum (gen)
"Consumes GEN, returning its minimum value."
+ :tests
+ (= ((range :to 5)) 0)
+ (= ((range :from -10 :to 0 :by 3)) -10)
+ (:fails ((seq "hey")))
+ :end
(fold (m nil) (x gen)
(if m (min m x) x)))
-(defun average (gen)
+(defun/t average (gen)
"Consumes GEN, returning its average value."
+ :tests
+ (= ((range :from 1 :to 4 :inclusive t)) 5/2)
+ (:signals ((seq nil)) division-by-zero) ; empty sum signals division by zero
+ (:fails ((seq "foo"))) ; numeric sequences only
+ :end
(let ((sum 0)
(count 0))
(for x gen
@@ -811,9 +844,12 @@ of indexes."
(incf count))
(/ sum count)))
-(defun argmax (fn gen)
+(defun/t argmax (fn gen)
"Consumes GEN. Returns a pair (X . VALUE) such that (FUNCALL FN X)
is maximal among the values of GEN. VALUE is the value of (FUNCALL FN X)"
+ :tests
+ (:program test-argmax)
+ :end
(fold (am nil)
(arg gen)
(let ((val (funcall fn arg)))
@@ -821,9 +857,12 @@ is maximal among the values of GEN. VALUE is the value of (FUNCALL FN X)"
(cons arg val)
am))))
-(defun argmin (fn gen)
+(defun/t argmin (fn gen)
"Consumes GEN. Returns a pair (X . VALUE) such that (FUNCALL FN X)
is minimal among the values of GEN. VALUE is the value of (FUNCALL FN X)"
+ :tests
+ (:program test-argmin)
+ :end
(fold (am nil)
(arg gen)
(let ((val (funcall fn arg)))