8cf0978477a8

Add some more useful functions
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sat, 02 Dec 2017 12:48:23 -0500
parents 1e90139a06b1
children 08b21b4d8af6
branches/tags (none)
files DOCUMENTATION.markdown losh.lisp make-docs.lisp package.lisp

Changes

--- a/DOCUMENTATION.markdown	Fri Oct 13 01:32:30 2017 -0400
+++ b/DOCUMENTATION.markdown	Sat Dec 02 12:48:23 2017 -0500
@@ -1344,6 +1344,20 @@
 
   
 
+## Package `LOSH.LISTS`
+
+Utilities for operating on lists.
+
+### `SOMELIST` (function)
+
+    (SOMELIST PREDICATE LIST)
+
+Call `predicate` on successive sublists of `list`, returning the first true result.
+
+  `somelist` is to `some` as `maplist` is to `mapcar`.
+
+  
+
 ## Package `LOSH.MATH`
 
 Utilities related to math and numbers.
@@ -1409,6 +1423,10 @@
 
 Return whether `n` is evenly divisible by `divisor`.
 
+  The value returned will be the quotient when true, `nil` otherwise.
+
+  
+
 ### `IN-RANGE-P` (function)
 
     (IN-RANGE-P LOW VALUE HIGH)
@@ -1903,6 +1921,28 @@
 
   
 
+### `PRODUCT` (function)
+
+    (PRODUCT SEQUENCE &KEY KEY)
+
+Return the product of all elements of `sequence`.
+
+  If `key` is given, it will be called on each element to compute the
+  multiplicand.
+
+  Examples:
+
+    (product #(1 2 3))
+    ; => 6
+
+    (product '("1" "2" "3") :key #'parse-integer)
+    ; => 6
+
+    (product '("1" "2" "3") :key #'length)
+    ; => 1
+
+  
+
 ### `PROPORTIONS` (function)
 
     (PROPORTIONS SEQUENCE &KEY (TEST 'EQL) (FLOAT T))
@@ -1926,6 +1966,30 @@
 
   
 
+### `SUMMATION` (function)
+
+    (SUMMATION SEQUENCE &KEY KEY)
+
+Return the sum of all elements of `sequence`.
+
+  If `key` is given, it will be called on each element to compute the addend.
+
+  This function's ugly name was chosen so it wouldn't clash with iterate's `sum`
+  symbol.  Sorry.
+
+  Examples:
+
+    (sum #(1 2 3))
+    ; => 6
+
+    (sum '("1" "2" "3") :key #'parse-integer)
+    ; => 6
+
+    (sum '("1" "2" "3") :key #'length)
+    ; => 3
+
+  
+
 ### `TAKE` (function)
 
     (TAKE N SEQ)
--- a/losh.lisp	Fri Oct 13 01:32:30 2017 -0400
+++ b/losh.lisp	Sat Dec 02 12:48:23 2017 -0500
@@ -118,8 +118,14 @@
   (* x x))
 
 (defun-inline dividesp (n divisor)
-  "Return whether `n` is evenly divisible by `divisor`."
-  (zerop (mod n divisor)))
+  "Return whether `n` is evenly divisible by `divisor`.
+
+  The value returned will be the quotient when true, `nil` otherwise.
+
+  "
+  (multiple-value-bind (quotient remainder) (floor n divisor)
+    (when (zerop remainder)
+      quotient)))
 
 
 (declaim (ftype (function (real real real)
@@ -2146,6 +2152,68 @@
                               el)))))
 
 
+(defun-inlineable summation (sequence &key key)
+  "Return the sum of all elements of `sequence`.
+
+  If `key` is given, it will be called on each element to compute the addend.
+
+  This function's ugly name was chosen so it wouldn't clash with iterate's `sum`
+  symbol.  Sorry.
+
+  Examples:
+
+    (sum #(1 2 3))
+    ; => 6
+
+    (sum '(\"1\" \"2\" \"3\") :key #'parse-integer)
+    ; => 6
+
+    (sum '(\"1\" \"2\" \"3\") :key #'length)
+    ; => 3
+
+  "
+  (if key
+    (iterate (for n :in-whatever sequence)
+             (sum (funcall key n)))
+    (iterate (for n :in-whatever sequence)
+             (sum n))))
+
+(defun-inlineable product (sequence &key key)
+  "Return the product of all elements of `sequence`.
+
+  If `key` is given, it will be called on each element to compute the
+  multiplicand.
+
+  Examples:
+
+    (product #(1 2 3))
+    ; => 6
+
+    (product '(\"1\" \"2\" \"3\") :key #'parse-integer)
+    ; => 6
+
+    (product '(\"1\" \"2\" \"3\") :key #'length)
+    ; => 1
+
+  "
+  (if key
+    (iterate (for n :in-whatever sequence)
+             (multiplying (funcall key n)))
+    (iterate (for n :in-whatever sequence)
+             (multiplying n))))
+
+
+;;;; Lists --------------------------------------------------------------------
+(defun somelist (predicate list)
+  "Call `predicate` on successive sublists of `list`, returning the first true result.
+
+  `somelist` is to `some` as `maplist` is to `mapcar`.
+
+  "
+  (iterate (for l :on list)
+           (thereis (funcall predicate l))))
+
+
 ;;;; Debugging & Logging ------------------------------------------------------
 (defun pr (&rest args)
   "Print `args` readably, separated by spaces and followed by a newline.
--- a/make-docs.lisp	Fri Oct 13 01:32:30 2017 -0400
+++ b/make-docs.lisp	Sat Dec 02 12:48:23 2017 -0500
@@ -17,6 +17,7 @@
         "LOSH.IO"
         "LOSH.ITERATE"
         "LOSH.LICENSING"
+        "LOSH.LISTS"
         "LOSH.MATH"
         "LOSH.MUTATION"
         "LOSH.PRIORITY-QUEUES"
--- a/package.lisp	Fri Oct 13 01:32:30 2017 -0400
+++ b/package.lisp	Sat Dec 02 12:48:23 2017 -0500
@@ -302,7 +302,14 @@
     :take
     :take-while
     :drop
-    :drop-while))
+    :drop-while
+    :summation
+    :product))
+
+(defpackage :losh.lists
+  (:documentation "Utilities for operating on lists.")
+  (:export
+    :somelist))
 
 (defpackage :losh.weightlists
   (:documentation
@@ -332,6 +339,7 @@
    :losh.io
    :losh.iterate
    :losh.licensing
+   :losh.lists
    :losh.math
    :losh.mutation
    :losh.priority-queues