Alternatives (v0.2.20141117) Released November 17th, 2014
Patrick Stein

I have uploaded a new version of my Alternatives library. In addition to the ALTERNATIVES macro, there is an ALTERNATIVES* macro which allows one to specify a name for the set of choices. Then, one can check the DOCUMENTATION to see which alternative was last macroexpanded.

(defun random-letter ()
  (alt:alternatives* random-letter-algorithm
    ***
    (:constant-a
     "Always pick the letter A."
     #\A)

     (:uniform
      "Choose any letter with equal probability"
      (random:random-elt "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))))

(documentation 'random-letter-algorithm 'alt:alternatives)
  => "CONSTANT-A
     Always pick the letter A."

Alternatives (v0.1.20141115) Released November 16th, 2014
Patrick Stein

I have now released the code that I mentioned in my previous post Code That Tells You Why which lets one keep multiple implementations around in code and switch between them manually without much trouble.

A link to the source code is here: nklein.com/software/alternatives/.

Code That Tells You Why November 13th, 2014
Patrick Stein

A 2006 article by Jeff Atwood titled Code Tells You How, Comments Tell You Why showed up on reddit/r/programming today.

It makes a good point. However, it got me thinking that for cases like the binary-search example in the article, it might be nice to see all of the alternatives in the code and easily be able to switch between them.

One way to accomplish this in Lisp is to abuse the #+ and #- reader macros:

(defun sum-i^2 (n)
  #+i-wanted-to-do-this
  (loop :for i :to n :summing (* i i))

  #+my-first-attempt-was-something-like-this
  (do ((i 0 (1+ i))
       (sum 0 (+ sum (* i i))))
      ((> i n) sum))

  #+but-i-could-not-do-that-because
  "Some people find a do-loop to hard to read
    (and 'too' too hard to spell, apparently)."


  #-now-i-know-better-and-can-do-this
  (/ (* n (1+ n) (1+ (+ n n)) 6))

This is less than ideal for a number of reasons, including: one needs to make sure to pick “feature” names that won’t actually ever get turned on, the sense of + and - seem backwards here, and switching to a different alternative requires editing two places.

Another Lisp alternative is to abuse the case form:

(defun sum-i^2 (n)
  (case :now-i-know-better-and-can-do-this
    (:i-wanted-to-do-this
     (loop :for i :to n :summing (* i i)))

    (:my-first-attempt-was-something-like-this
     (do ((i 0 (1+ i))
          (sum 0 (+ sum (* i i))))
         ((> i n) sum)))

    (:but-i-could-not-do-that-because
     "Some people find a do-loop to hard to read
    (and 'too' too hard to spell, apparently)."
)

    (:now-i-know-better-and-can-do-this
     (/ (* n (1+ n) (1+ (+ n n)) 6)))))

This is better. No one can doubt which alternative is in use. It is only one edit to switch which alternative is used. It still feels pretty hackish to me though.

One can clean it up a bit with some macrology.

(defmacro alternatives (&body clauses)
  (flet ((symbol-is-***-p (sym)
           (and (symbolp sym)
                (string= (symbol-name sym) "***")))
         (final-clause-p (clause)
           (when (listp clause)
             (destructuring-bind (tag &body body) clause
               (when (and (symbolp tag)
                          (member (symbol-name tag)
                                  '("***" "FINAL" "BLESSED")
                                  :test #'string=))
                 body)))))
    (anaphora:acond
      ((member-if #'symbol-is-***-p clauses)
       (let ((clause (first (rest anaphora:it))))
         `(progn
            ,@(rest clause))))

      ((find-if #'final-clause-p clauses)
       `(progn
          ,@(rest anaphora:it)))

      ((last clauses)
       `(prog
          ,@(rest (first anaphora:it)))))))

With this macro, one can now rewrite the sum-i^2 function quite readably:

(defun sum-i^2 (n)
  (alternatives
    (i-wanted-to-do-this
     (loop :for i :to n :summing (* i i)))

    (my-first-attempt-was-something-like-this
     (do ((i 0 (1+ i))
          (sum 0 (+ sum (* i i))))
         ((> i n) sum)))

    (but-i-could-not-do-that-because
     "Some people find a do-loop to hard to read
    (and 'too' too hard to spell, apparently)."
)

    (now-i-know-better-and-can-do-this
     (/ (* n (1+ n) (1+ (+ n n)) 6)))))

If I wanted to try the my-first-attempt-was-something-like-this clause, I could stick a *** before that clause or change its name to *** or final or blessed, or I could move that clause into the last spot.

There is still an onus on the developer to chose useful alternative names. In most production code, one wants to clean out all of the dead code. On the other hand, during development or for more interactive code bodies, one might prefer to be able to see the exact “How” that goes with the “Why” and easily be able to swap between them.

(Above macro coming in well-documented library form, hopefully this weekend.)

Clozure Common Lisp on the Raspberry Pi April 8th, 2014
Patrick Stein

I finally ordered a Raspberry Pi last week. It arrived yesterday. Last night, I installed the Raspbian (Debian for Raspberry Pi) distro. Then, I followed Rainer Joswig’s excellent instructions on how to get Clozure Common Lisp running on the Raspberry Pi.

The only think that I would add to Rainer’s presentation is that Raspbian didn’t come with m4(1) out of the box, but it is needed when you make all to rebuild Clozure.

Hacks and glory await!

Also, Linux pro-tip: If you are thinking of renaming your only account on the machine, make sure you add the new name to a group with sudo privileges and make sure you get both /etc/passwd and /etc/shadow in the same sudo.

Edit: Rainer correctly points out that his article does say you will need to install m4 if you haven’t already. I just missed it.

Ranked Choice Voting Visualization November 9th, 2013
Patrick Stein

There were 35 candidates registered for the Minneapolis mayoral race this year. Minneapolis approved ranked-choice voting in 2006. I have great respect and deep sympathy for those who had to tabulate all of those votes. And, because there is no FEC-certified software for counting this type of vote, it was a huge human effort.

The Minnesota Secretary of State’s website has information about which candidates where eliminated in which of the 33 elimination rounds in the tabulation. I scraped the data from their Excel spreadsheet, added some Vecto, and put together some worm-trail charts. I couldn’t quite use Zach’s wormtrails library because I wanted to show how an eliminated candidates votes were redistributed (to other candidates who were lower-ranked choices or to the exhausted bucket). Also, note: the tabulated data on the Minnesota Secretary of State’s website is insufficient to form an accurate proportioning in rounds when multiple candidates are eliminated. In those cases, I just assumed that all candidates whose votes were redistributed were redistributed in the same proportions to the candidates who gained votes because of the eliminations in that round.

About 450 lines of Lisp code later, I came up with images like the one below (click to see it at full-size):
Minneapolis Mayoral 2013 RCV rounds 22 through 33

The white worm-trail through the center is the exhausted pile. Unfortunately, the eliminated candidates in the first 25 or so rounds had so few votes that I’d have to render these images wall-sized for you to get any idea what proportion of their votes went where. In the final few rounds, you can see some detail even with a semi-reasonable file size. I suppose I should see if I can wrangle the data from the St. Paul race which only had six candidates (and thus fewer than six rounds of counting).

Here is the chart broken up into three sections to make it a bit more manageable:
Minneapolis Mayoral 2013 RCV rounds 1 through 11 Minneapolis Mayoral 2013 RCV rounds 11 through 22 Minneapolis Mayoral 2013 RCV rounds 22 through 33

Here is a link to all rounds in one big file. And, here is the source code: rcv.lisp.

Note for Lisp folks: I don’t like the above code. I like short functions, but I also like using flet or labels to make functions that are still within lexical scope of a whole mess of variables. Anyone else come to a good resolution between those two things? Is bundling data in structs and classes really the right thing or a sea of global specials?

Updates In Email

Email:

l