# HG changeset patch # User Steve Losh # Date 1498156792 0 # Node ID 410ea6dead954a79a4b62511ba670fe0586f0e96 # Parent 94e507bedb6b68a579c9801937582c7d03fdcbe4 Add `gimme` and `gnuplot-histogram` and a couple other things diff -r 94e507bedb6b -r 410ea6dead95 DOCUMENTATION.markdown --- 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. diff -r 94e507bedb6b -r 410ea6dead95 losh.lisp --- 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 diff -r 94e507bedb6b -r 410ea6dead95 package.lisp --- 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