410ea6dead95

Add `gimme` and `gnuplot-histogram` and a couple other things
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Thu, 22 Jun 2017 18:39:52 +0000
parents 94e507bedb6b
children 15ab2e1331a1
branches/tags (none)
files DOCUMENTATION.markdown losh.lisp package.lisp

Changes

--- a/DOCUMENTATION.markdown	Sun May 07 23:41:20 2017 +0000
+++ b/DOCUMENTATION.markdown	Thu Jun 22 18:39:52 2017 +0000
@@ -422,32 +422,6 @@
 
   
 
-### `RECURSIVELY` (macro)
-
-    (RECURSIVELY BINDINGS
-      &BODY
-      BODY)
-
-Execute `body` recursively, like Clojure's `loop`/`recur`.
-
-  `bindings` should contain a list of symbols and (optional) starting values.
-
-  In `body` the symbol `recur` will be bound to the function for recurring.
-
-  This macro doesn't perform an explicit tail-recursion check like Clojure's
-  `loop`.  You know what you're doing, right?
-
-  Example:
-
-      (defun length (some-list)
-        (recursively ((list some-list)
-                      (n 0))
-          (if (null list)
-            n
-            (recur (cdr list) (1+ n)))))
-
-  
-
 ### `WHEN-FOUND` (macro)
 
     (WHEN-FOUND VAR
@@ -563,6 +537,12 @@
 
   
 
+### `GIMME` (macro)
+
+    (GIMME N
+      &BODY
+      BODY)
+
 ### `PHT` (function)
 
     (PHT HASH-TABLE &OPTIONAL (STREAM T))
@@ -662,7 +642,7 @@
 
 ### `START-PROFILING` (function)
 
-    (START-PROFILING &OPTIONAL CALL-COUNT-PACKAGES)
+    (START-PROFILING &KEY CALL-COUNT-PACKAGES (MODE :CPU))
 
 Start profiling performance.  SBCL only.
 
@@ -829,8 +809,8 @@
                   (SIZE-X 1200) (SIZE-Y 800) (LABEL-X) (LABEL-Y)
                   (LINE-TITLE 'DATA) (LINE-WIDTH 4) (SMOOTH NIL) (AXIS-X NIL)
                   (AXIS-Y NIL) (MIN-X NIL) (MAX-X NIL) (MIN-Y NIL) (MAX-Y NIL)
-                  (GRAPH-TITLE) (LOGSCALE-X NIL) (LOGSCALE-Y NIL)
-                  &ALLOW-OTHER-KEYS)
+                  (TICS-X NIL) (GRAPH-TITLE) (LOGSCALE-X NIL) (LOGSCALE-Y NIL)
+                  (BOX-WIDTH NIL) &ALLOW-OTHER-KEYS)
 
 Return the formatted command line arguments for the given gnuplot arguments.
 
@@ -862,6 +842,18 @@
 
   
 
+### `GNUPLOT-HISTOGRAM` (function)
+
+    (GNUPLOT-HISTOGRAM DATA &KEY (BIN-WIDTH 1))
+
+Plot `data` as a histogram with gnuplot.
+
+  `bin-width` should be the desired width of the bins.  The bins will be
+  centered on multiples of this number, and data will be rounded to the nearest
+  bin.
+
+  
+
 ## Package `LOSH.HASH-SETS`
 
 Simple hash set implementation.
--- a/losh.lisp	Sun May 07 23:41:20 2017 +0000
+++ b/losh.lisp	Thu Jun 22 18:39:52 2017 +0000
@@ -1587,6 +1587,12 @@
   (let ((kwd (if generate 'generate 'for)))
     `(,kwd (,var) :in-hashtable (hash-set-storage ,hset))))
 
+(defmacro-driver (FOR var RECURSIVELY expr INITIALLY init)
+  (let ((kwd (if generate 'generate 'for)))
+    `(progn
+       (initially (setf ,var ,init))
+       (,kwd ,var = ,expr))))
+
 
 ;;;; Hash Tables --------------------------------------------------------------
 (defun mutate-hash-values (function hash-table)
@@ -2053,7 +2059,7 @@
                      :min-percent 0.5)))
 
 #+sbcl
-(defun start-profiling (&optional call-count-packages)
+(defun start-profiling (&key call-count-packages (mode :cpu))
   "Start profiling performance.  SBCL only.
 
   `call-count-packages` should be a list of package designators.  Functions in
@@ -2067,7 +2073,7 @@
     (mapcar #'string-upcase <>)
     (mapc #'sb-sprof::profile-call-counts <>))
   (sb-sprof::start-profiling :max-samples 50000
-                             :mode :cpu
+                             :mode mode
                              ; :mode :time
                              :sample-interval 0.01
                              :threads :all))
@@ -2088,6 +2094,11 @@
        (stop-profiling))))
 
 
+(defmacro gimme (n &body body)
+  `(iterate (repeat ,n)
+     (collect (progn ,@body))))
+
+
 ;;;; CLOS ---------------------------------------------------------------------
 (defun build-slot-definition (conc-name slot-spec)
   (destructuring-bind (name &key
@@ -2541,9 +2552,11 @@
                      (max-x nil)
                      (min-y nil)
                      (max-y nil)
+                     (tics-x nil)
                      (graph-title)
                      (logscale-x nil)
                      (logscale-y nil)
+                     (box-width nil)
                      &allow-other-keys)
   "Return the formatted command line arguments for the given gnuplot arguments.
 
@@ -2564,7 +2577,9 @@
       (f "set border linewidth 1")
       (f "set style line 10 dashtype 2 linewidth 3 linecolor \"#666666\"")
       (when axis-x (f "set xzeroaxis linestyle 10"))
+      (when tics-x (f "set xtics ~A" tics-x))
       (when axis-y (f "set yzeroaxis linestyle 10"))
+      (when box-width (f "set boxwidth ~A" box-width))
       (when graph-title (f "set title '~A'" (esc graph-title)))
       (when label-x (f "set xlabel '~A'" (esc label-x)))
       (when label-y (f "set ylabel '~A'" (esc label-y)))
@@ -2652,6 +2667,26 @@
     ,@args))
 
 
+(defun gnuplot-histogram (data &key (bin-width 1))
+  "Plot `data` as a histogram with gnuplot.
+
+  `bin-width` should be the desired width of the bins.  The bins will be
+  centered on multiples of this number, and data will be rounded to the nearest
+  bin.
+
+  "
+  (-<> data
+    (mapcar (lambda (y)
+              (* bin-width (round y bin-width)))
+            <>)
+    frequencies
+    hash-table-alist
+    (gnuplot <> :style :boxes
+             :min-y 0
+             :line-width 1
+             :box-width (* bin-width 1.0))))
+
+
 ;;;; Licensing ----------------------------------------------------------------
 ;;; Original code from @dk_jackdaniel:
 ;;; http://paste.lisp.org/display/327154
--- a/package.lisp	Sun May 07 23:41:20 2017 +0000
+++ b/package.lisp	Thu Jun 22 18:39:52 2017 +0000
@@ -17,6 +17,10 @@
              :collect `(:export ,@(external-symbols parent-package)))))
 
 
+(defpackage :losh.base
+  (:export :recursively))
+
+
 (defpackage :losh.arrays
   (:documentation "Utilities related to arrays.")
   (:export
@@ -52,6 +56,7 @@
     :defclass*))
 
 (defpackage :losh.control-flow
+  (:use :losh.base)
   (:documentation "Utilities for managing control flow.")
   (:export
     :-<>
@@ -77,6 +82,7 @@
     :comment
     :aesthetic-string
     :structural-string
+    :gimme
     #+sbcl :start-profiling
     #+sbcl :stop-profiling
     #+sbcl :profile
@@ -105,6 +111,7 @@
     :gnuplot-args
     :gnuplot-expr
     :gnuplot-function
+    :gnuplot-histogram
     :x))
 
 (defpackage :losh.hash-sets
@@ -151,7 +158,7 @@
     :read-all-from-string))
 
 (defpackage :losh.iterate
-  (:use :iterate) ; need this for iterate's `for` symbol fuckery
+  (:use :iterate :losh.base) ; need this for iterate's `for` symbol fuckery
   (:documentation "Custom `iterate` drivers and clauses.")
   (:export
 
@@ -168,6 +175,7 @@
     :in-sequences
     :in-whatever
     :index-of-flat-array
+    :initially
     :into
     :macroexpand-iterate
     :modulo
@@ -175,6 +183,7 @@
     :pairs-of-list
     :per-iteration-into
     :real-time
+    :recursively
     :run-time
     :since-start-into
     :skip-origin