d25b6f52fad1

Add `enumerate`, expose `-<>`, add gnuplot terms
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Fri, 20 Jan 2017 13:59:11 +0000
parents 5dd997c40424
children ba324d052c50
branches/tags (none)
files DOCUMENTATION.markdown losh.lisp package.lisp

Changes

--- a/DOCUMENTATION.markdown	Thu Jan 19 17:05:14 2017 +0000
+++ b/DOCUMENTATION.markdown	Fri Jan 20 13:59:11 2017 +0000
@@ -294,6 +294,12 @@
 
 Utilities for managing control flow.
 
+### `-<>` (macro)
+
+    (-<> &REST FORMS)
+
+Thread the given forms, with `<>` as a placeholder.
+
 ### `GATHERING` (macro)
 
     (GATHERING
@@ -750,10 +756,11 @@
 
 ### `GNUPLOT-ARGS` (function)
 
-    (GNUPLOT-ARGS &KEY (FILENAME plot.png) (STYLE :LINES) (SIZE-X 1200)
-                  (SIZE-Y 800) (LABEL-X) (LABEL-Y) (LINE-TITLE 'DATA)
-                  (LINE-WIDTH 4) (AXIS-X NIL) (AXIS-Y NIL) (GRAPH-TITLE)
-                  (LOGSCALE-X NIL) (LOGSCALE-Y NIL) &ALLOW-OTHER-KEYS)
+    (GNUPLOT-ARGS &KEY (OUTPUT :QT) (FILENAME plot.png) (STYLE :LINES)
+                  (SIZE-X 1200) (SIZE-Y 800) (LABEL-X) (LABEL-Y)
+                  (LINE-TITLE 'DATA) (LINE-WIDTH 4) (AXIS-X NIL) (AXIS-Y NIL)
+                  (GRAPH-TITLE) (LOGSCALE-X NIL) (LOGSCALE-Y NIL)
+                  &ALLOW-OTHER-KEYS)
 
 Return the formatted command line arguments for the given gnuplot arguments.
 
@@ -1403,11 +1410,33 @@
 
   
 
+### `ENUMERATE` (function)
+
+    (ENUMERATE SEQUENCE &KEY (START 0) (STEP 1) KEY)
+
+Return an alist of `(n . element)` for each element of `sequence`.
+
+  `start` and `step` control the values generated for `n`, NOT which elements of
+  the sequence are enumerated.
+
+  Examples:
+
+    (enumerate '(a b c))
+    ; => ((0 . A) (1 . B) (2 . C))
+
+    (enumerate '(a b c) :start 1)
+    ; => ((1 . A) (2 . B) (3 . C))
+
+    (enumerate '(a b c) :key #'ensure-keyword)
+    ; => ((0 . :A) (1 . :B) (2 . :C))
+
+  
+
 ### `EXTREMA` (function)
 
     (EXTREMA PREDICATE SEQUENCE)
 
-Return the smallest and largest elements of `sequence` according to `predicate`
+Return the smallest and largest elements of `sequence` according to `predicate`.
 
   `predicate` should be a strict ordering predicate (e.g. `<`).
 
--- a/losh.lisp	Thu Jan 19 17:05:14 2017 +0000
+++ b/losh.lisp	Fri Jan 20 13:59:11 2017 +0000
@@ -2,13 +2,17 @@
 
 ;;;; Sanity -------------------------------------------------------------------
 (defmacro -<> (&rest forms)
+  "Thread the given forms, with `<>` as a placeholder."
   ;; I am going to lose my fucking mind if I have to program lisp without
   ;; a threading macro, but I don't want to add another dep to this library, so
   ;; here we are.
   (if (null forms)
     '<>
-    `(let ((<> ,(first forms)))
-       (-<> ,@(rest forms)))))
+    (destructuring-bind (form . remaining) forms
+      `(let ((<> ,(if (symbolp form)
+                    `(,form <>)
+                    form)))
+         (-<> ,@remaining)))))
 
 
 ;;;; Types --------------------------------------------------------------------
@@ -1677,7 +1681,7 @@
 
 
 (defun extrema (predicate sequence)
-  "Return the smallest and largest elements of `sequence` according to `predicate`
+  "Return the smallest and largest elements of `sequence` according to `predicate`.
 
   `predicate` should be a strict ordering predicate (e.g. `<`).
 
@@ -1693,6 +1697,31 @@
            (finally (return (values min max)))))
 
 
+(defun enumerate (sequence &key (start 0) (step 1) key)
+  "Return an alist of `(n . element)` for each element of `sequence`.
+
+  `start` and `step` control the values generated for `n`, NOT which elements of
+  the sequence are enumerated.
+
+  Examples:
+
+    (enumerate '(a b c))
+    ; => ((0 . A) (1 . B) (2 . C))
+
+    (enumerate '(a b c) :start 1)
+    ; => ((1 . A) (2 . B) (3 . C))
+
+    (enumerate '(a b c) :key #'ensure-keyword)
+    ; => ((0 . :A) (1 . :B) (2 . :C))
+
+  "
+  (iterate (for el :in-whatever sequence)
+           (for n :from start :by step)
+           (collect (cons n (if key
+                              (funcall key el)
+                              el)))))
+
+
 ;;;; Debugging & Logging ------------------------------------------------------
 (defun pr (&rest args)
   "Print `args` readably, separated by spaces and followed by a newline.
@@ -2216,6 +2245,7 @@
           (remove nil args)))
 
 (defun gnuplot-args (&key
+                     (output :qt)
                      (filename "plot.png")
                      (style :lines)
                      (size-x 1200)
@@ -2239,9 +2269,13 @@
   (flet ((esc (string) (remove #\' (aesthetic-string string)))
          (f (&rest args) (apply #'format nil args)))
     (gnuplot-args%
-      (f "set terminal pngcairo dashed size ~D,~D font \"Lucida Grande,20\""
-         size-x size-y)
-      (f "set output '~A'" (esc filename))
+      (ecase output
+        ((:x :x11) (f "set terminal x11 persist"))
+        (:qt (f "set terminal qt persist"))
+        (:png
+         (f "set terminal pngcairo dashed size ~D,~D font \"Lucida Grande,20\""
+            size-x size-y)
+         (f "set output '~A'" (esc filename))))
       (f "set border linewidth 1")
       (f "set style line 10 dashtype 2 linewidth 3 linecolor \"#666666\"")
       (when axis-x (f "set xzeroaxis linestyle 10"))
--- a/package.lisp	Thu Jan 19 17:05:14 2017 +0000
+++ b/package.lisp	Fri Jan 20 13:59:11 2017 +0000
@@ -54,6 +54,8 @@
 (defpackage :losh.control-flow
   (:documentation "Utilities for managing control flow.")
   (:export
+    :-<>
+    :<>
     :recursively
     :recur
     :when-found
@@ -242,6 +244,7 @@
   (:documentation "Utilities for operating on sequences.")
   (:export
     :extrema
+    :enumerate
     :prefix-sums
     :frequencies
     :proportions