## Fog of Light – Starting to Add Star-FieldsMay 28th, 2017 Patrick Stein

I have finally written my first OpenGL code using GLSL. Whew. That took way too long to get all working correctly. I promise, soon, I will upload some sample code so that others may not have to stumble as long as I did.

For the star-field, I generate a few thousand 2-D points. Each point has its own radius, its own opacity, and its own color.

I put these all into an OpenGL array buffer. Then, the vertex shader copies data out of my struct to set the color and the point size. Then, the fragment shader turns the color into two, overlapping radial gradients (one that is half the radius of the other) by modulating the color’s opacity.

Next up will be nebulae, then planets/asteroids in the local system.

## Fog of Light – Getting UnderwayMay 15th, 2017 Patrick Stein

Dauntless (The Lost Fleet, Book 1) was the first science-fiction book I read that tried to deal with space combat with the real-world constraint that light only travels so fast. It takes light eight minutes to get from the Sun to Earth. It takes light more than a second to get from the Earth to the Moon. Depending on where they are in their orbits, it takes between three minutes and twenty-two minutes to get light from Mars to Earth.

Imagine that you’re a star-ship. You and your companions have just warped into a new star system. You see a flotilla of enemy ships about 45 light-minutes away. That means, you’ve got 45 minutes before that flotilla can possibly even know that you’re in their star system. How much can you get done in that time? Once they can see you, how much can you mislead them on your target if they’re going to be operating on data about where you were heading more than half an hour ago?

For years, I have been batting around this concept, hammering it into a game. I have finally gotten started on it.

Armed with some functions like these, I am constructing values which change at points in space-time and querying the value visible from other points in space-time.

(defgeneric get-nearest-value (space-time-value space-time-point)
...
(:documentation "Find the observable value of a quantity
SPACE-TIME-VALUE when observed from a given location
SPACE-TIME-POINT. This method finds the most-recent
value V0 (at location P0) for this data when viewed from
the given location. This method returns (VALUES V0 P0).
This method makes no effort to interpolate the results."
))

Hopefully, there will be plenty more coming in the near future.

## The Less You Know (An Unspoken Tenet of Clean Architecture)February 7th, 2016 Patrick Stein

In response to my previous article, Holger Schauer asked why I implemented the use-cases with classes rather than having the book repository passed into the `browse-books` method or putting it into the abstract base-class `browse-books-use-case` rather than in the implementation.

(defstruct browse-books-request
book-repository)

(defgeneric browse-books (request response))

;; -- or --

(defgeneric browse-books (book-repository request response)

;; -- or --

(defclass browse-books-use-case ()

I started to reply, but I found that I was having trouble keeping my response to a reasonable length. So, here, you are subjected to my unreasonably long response.

For reference, here is the repository from the previous post.

#### Java’s Influence

I chose to model the use-cases as classes to be faithful to all of the implementations that I’ve seen of Clean Architecture. Uncle Bob, in particular, does most of his videos and talks using Java or Ruby. When he uses Ruby, he still tends to use the same OO organization that he would use if he were writing Java.

One aspect of Java is that everything has to be a method on some class. If you want to declare a method somewhere but have its implementation somewhere else, you can do this with an abstract base class or an interface. You cannot, for example, declare an abstract static method as you can in CLOS (or even C).

Java’s single-inheritance makes it very awkward in general to use abstract base classes. If the `book-repository` slot were on the `browse-books-use-case` rather than on the implementation, this would have to be an abstract base-class and direct inheritance if it were in Java. If the `book-repository` slot is on the implementation rather than on the `browse-books-use-case`, then someone writing this in Java could use an interface and an implementation of that interface.

I wrote this blog post using Lisp/CLOS. However, for the actual project that I am working on, I have opted to use PHP. PHP shares Java’s inheritance restrictions. A class can only have one superclass but it can implement any number of interfaces.

#### The Stated Advantages of Clean Architecture

When Uncle Bob talks about why to use Clean Architecture, he tends to focus on these things:

• Ability to defer decisions about the frontend and backend
• Ability to test the core logic of the application easily
• Ability to deploy your application in pieces

The adapters depend on interfaces defined in the application. The application does not depend on anything defined by the frontend or the backend. As such, deciding which frameworks to use on the frontend or which database to use on the backend can be deferred for a long time during the development process. Uncle Bob often describes how on FitNesse they developed using the filesystem as the database backend fully intending to plug in a relational database later in the project. In the end, they decided that the filesystem backend they had created served their purposes just fine. When they came upon a client who had requirements that all of the dynamic content be stored in their corporate database, they rewrote an adapter for that customer to use the database rather than the filesystem.

Clean Architecture applications are easy to test because the application code isn’t interwoven with the presentation code or the database code. One can create mocks (even test-specific mocks) for the repositories and front-ends that do whatever the test needs to have done. They can do it quickly, without temporary databases or network overhead.

In a Clean Architecture deployment of my application in Java, I might have one JAR file for the book repository implementation, one JAR file for the Console frontend, one JAR file for the application core logic, and one JAR file that wires all of those other pieces together on startup. If I need to incorporate a different database, then I only need to update the book repository implementation JAR and (maybe) the JAR file that wires the pieces together. I don’t have to redeploy my entire application every time the database changes. I don’t have to retest every bit of application logic. Everything is nicely contained.

#### An Unspoken Benefit of Clean Architecture

One of the ways that Clean Architecture keeps its dependencies in check is by making all of the interfaces going into or out of your application use primitive types or dumb structures for parameter passing. The unspoken benefit of this is that it encourages you to keep the interfaces as spartan as possible.

If the controller (the `console` in my sample application) that is invoking the use case doesn’t absolutely need to know there is a book repository involved, then it shouldn’t know about it. The book repository cannot be passed from the controller to the use case using primitive types and dumb structures.

The controller’s job is to take input from the user, turn it into a request, invoke the use case with that request, and present the response back to the user. There is no input that the controller can get from the user which will allow it to instantiate a book repository. It could, of course, pull it from global state as it pulled the use case. However, the less it needs to know, the better.

This separation has other benefits, as well. In Lisp, especially, one could imagine interacting with the application through the REPL. So, rather than implementing the simple REPL that I did with my `console`, I could have made a `browse` function that invokes the use-case and returns the results.

(defun browse ()
(let ((request (make-browse-books-request))
(response (make-browse-books-response)))
(browse-books *browse-books-use-case* request response)
(mapcar #'book-summary-to-plist
(browse-books-response-list-of-book-summaries response))))

If everything is going to happen within my one Lisp image, then it would be fine to keep a `*book-repository*` global to pass into the use case. However, if I want to share the book repository between multiple users, each at their own REPL, then it no longer makes sense that each REPL would need a handle to the book repository.

My `browse` function doesn’t need to know whether the use case it is interacting with is the actual implementation or just a proxy for the implementation. In the client-server case, it makes little sense for the client to have any idea that there is a book repository instance.

I suppose there are some classes of application where one might want to work on a remote repository but keep the application logic local. If that were the case, then one would want the book repository to be the interface which has the proxy and server. However, nothing in the architecture mentioned in the previous post precludes that use. If we had put the book repository into the interface for the use case rather than in its implementation, then we need to at least pretend there is a book repository on the local client even when everything is going to happen on the server.

#### Conclusion

An accidental benefit of Clean Architecture’s insistence on primitive or dumb-struct parameters to use-cases is that the parameters end up only reflecting the minimal amount of information that is specific to the current request. Any state that is common across requests is a part of the internal state of the use-case.

Because of this, code that is interacting with the use case only to know the little bit that makes them different from other people using the use case. This results in very simple interfaces to the use case and the a great deal of flexibility in implementation.

## Exploring Clean ArchitectureFebruary 4th, 2016 Patrick Stein

This is the first in what will likely be a series of blog posts about Clean Architecture. Uncle Bob Martin has written numerous blog posts and given lots of talks about it.

The goal of Clean Architecture is to have the directory structure of your application shout out what your application does rather than what framework was used to present your application or what database is nestled in the depths of your application. Your program is divided into Entities, Use Cases, and Interface Adapters.

Entities encapsulate “Enterprise-wide business rules.” Use Cases encapsulate “Application-specific business rules.” Interfaces and Adapters represent how your Use Cases want to interact with the outside world (e.g. databases, users, printers, etc.).

In Clean Architecture, the Entities cannot know that the Use Cases exist and the Use Cases cannot know anything about the Adapters except for the Interface to them which is defined by the Use Case rather than by the Adapter. The Use Case does not know whether the application is being used from the command-line or from the web or from a remote service calling into it. The Use Case does not know whether the data is being stored in the file system or in a relational database (or conjured from the ether as needed). Nothing in the Adapters can know anything about the Entities.

#### Simple Example

I have a project that I am just starting. I thought I would use this new project to see how Clean Architecture works for me.

There are large number of talks and videos about Clean Architecture. However, there are not many examples of it despite several years of Stack Overflow questions and blog posts asking for examples.

There are a few simple examples around the web. The most notable is Mark Paluch’s Clean Architecture Example. It is just big enough to get a sense of how things hang together. If you’re willing to put up with Java’s insane directory hierarchies, you can get a pretty good idea of what the application does just by poking around the Use Cases directory.

#### My First Use Case

My first Use Case is to let the User browse a list of Book Summaries. The User should be able to sort by Title, Author, Publication Date, or Date the Book was acquired. The User should be able to filter the list based upon Genre or Keyword. The Use Case should allow the caller to implement pagination, so the Use Case needs to support returning up to a given number of Book Summaries starting with a specific number.

Some might argue that that is multiple Use Cases glommed together. If that were the case, then I would need some way to pipeline together Use Cases if I’m going to make any sort of reasonably navigable app atop my Use Cases.

#### The Simplified Version of my First Use Case

Let’s just say the User wishes to see a list of all of the Book Summaries. The User is fine with seeing all of them at once in whatever order my app sees fit.

This simple version of the Use Case is implemented in an accompanying repository under the tag `the-dream`.

The architecture consists of some simple structures with no “business logic” in them at all: `book-summary` and `book`.

(defstruct book-summary
isbn
title
author
cover-page-thumbnail)

(defstruct book
isbn
title
author
cover-page-thumbnail
cover-page-fullsize
list-of-thumbnails
table-of-contents
synopsis
publication-date
list-of-genres
list-of-keywords)

There is one use case `browse-books` which defines the use-case interface `browse-books-use-case` along with its input structure `browse-books-request` and its output structure `browse-books-response`. The use case defines the method `browse-books` which must be called with a `browse-books-use-case` instance, a `browse-books-request` instance, and `browse-books-response` instance.

(defstruct browse-books-request)

(defstruct browse-books-response
list-of-book-summaries)

(defclass browse-books-use-case ()
())

(defgeneric browse-books (use-case request response))

In my implementation, the `browse-books-response` is a simple data structure. One could easily imagine that the `browse-books` method would return one rather than filling one in that was passed to it. In some variants of Clean Architecture (like the Paluch example cited above), the response model is a class instance upon which a method is called to complete the interaction. But, it would have to be clear from the outset that anyone using this Use Case cannot depend on it being synchronous or asynchronous.

The use case also defines the `book-repository` interface that it needs.

(defclass book-repository ()
())

(defgeneric find-book-by-isbn (book-repository isbn))
(defgeneric all-books (book-repository))

In the Paluch example, all of the use cases share the same repository interfaces (though Paluch and others have separate repository interfaces for Users and Invoices and Items). In several of Uncle Bob’s videos, he makes the claim (or claims equivalent to the claim) that each use case should define an interface for just the methods it needs to use on a Book repository. In this use case, it would need only the ability to retrieve the list of Books and so I should not have defined `find-book-by-isbn` here at all, and I should have named this interface `browse-books-book-repository`.

I wrote `browse-books-impl` class which extends the `browse-book-use-case`. It takes an instance of `book-repository` on construction.

(defclass browse-books-impl (browse-books-use-case)

(defun make-browse-books-use-case (book-repository)
(check-type book-repository book-repository)
(make-instance 'browse-books-impl :book-repository book-repository))

It uses that to retrieve the list of Books. Then, it creates a `book-summary` from each `book` instance retrieved from the `book-repository`.

(defun summarize-book (book)
(check-type book book)
(make-book-summary :isbn (book-isbn book)
:title (book-title book)
:author (book-author book)
:cover-page-thumbnail (book-cover-page-thumbnail book)))

(defmethod browse-books ((use-case browse-books-impl)
(request browse-books-request)
(response browse-books-response))
(let* ((books (all-books (book-repository use-case)))
(summaries (mapcar #'summarize-book books)))
(setf (browse-books-response-list-of-book-summaries response) summaries))
response)

To test the design so far, I wrote `in-memory-book-repository` backend which implements the `book-repository` interface that was defined in the Use Case.

(defclass in-memory-book-repository (book-repository)

(defun make-in-memory-book-repository (books)
(check-type books list)
(assert (every #'book-p books))
(make-instance 'in-memory-book-repository :books books))

(defmethod all-books ((book-repository in-memory-book-repository))
(mapcar #'copy-book (books book-repository)))

I also wrote a `console` frontend which invokes the `browse-books-use-case`.

(defun console-browse-books ()
(let ((request (make-browse-books-request))
(response (make-browse-books-response)))
(browse-books *browse-books-use-case* request response)
(mapcar #'console-print-summary
(browse-books-response-list-of-book-summaries response))
(values)))

...

(defun console-main-loop ()
(catch 'console-quit
(with-standard-io-syntax
(loop
:do (mapc #'console-print
(multiple-value-list

To tie it all together, I wrote `app-context` which holds the current `browse-books` instance.

(defvar *browse-books-use-case*)

And, I wrote the `app` which creates an instance of the `in-memory-book-repository` and creates the `browse-books-impl` for the `app-context`. Then, it runs the main loop of the `console` frontend.

(defun run-console-app-with-memory-db (&optional (books *book-list*))
(let* ((book-repo (make-in-memory-book-repository books))
(*browse-books-use-case* (make-browse-books-use-case book-repo)))
(console-main-loop)))

Already, in this simple interface, I am torn. For this Use Case, I do not need the repository to return me the list of Books. I could, instead, ask the repository to return me the list of Book Summaries. If I do that, my application is just a fig-leaf over the repository.

(defgeneric all-book-summaries (book-repository))

Well, the argument against asking the repository for Book Summaries is that it should not be up to the database to decide how I would like to have my Books summarized. That certainly seems like it should be “business logic” and probably “application specific” business logic at that.

So, fine. I will have the repository return Books and the Use Case will summarize them.

Now, let me extend the Use Case the next little bit forward. What if I want to support pagination? My choices are to push the pagination down to the repository so that I can ask it to give me up to 20 Books starting with the 40th Book. Or, I can let the repository give me all of the books and do the pagination in the Use Case.

(defstruct browse-books-request
start max-results)

Here, I can find no guidance in any of the Clean Architecture videos that I have watched nor in the examples that I have found online. Everyone seems happy with the repositories being able to return one item given that item’s unique identifier or return all of the items.

If the repository is going to return all of the Books, then why wouldn’t my Use Case just return them all and leave the caller to do any pagination that is needed?

This works fine when there are a few dozen books and they are small. It does not scale, and I don’t know how it is supposed to scale without pushing most of the responsibility onto the repository.

(defgeneric all-books-in-range (book-repository start max-results))

Sure, I can push the responsibility onto the repository. But, one of the reasons that Clean Architecture is so structured is to allow easy testing of all of the application logic. The more that I push into the repository, the less that I actually exercise when I run my unit tests with my mock repository (and the more complex my mock repository should probably be).

One possible approach would be to have the `all-books` method instead be `all-isbns`. Then, I can retrieve all of the ISBNs and use `find-book-by-isbn` to get all of the books.

Now, if I want to sort by Author then by Title, I need to:

• fetch all of the ISBNs `all-isbns`,
• fetch each ISBN’s title,
• sort my ISBNs by title,
• fetch each ISBN’s author,
• stable-sort my ISBNs by author,
• clip to my range,
• fetch each book in my range,
• summarize each fetched book

Or, I have to write an SQL query, that can do all of that in one database call instead of 2N + R + 1 calls (where N is the number of books in the database and R is the number of books in my range), making my Use Case a fig-leaf again.

## Population in Politics, Simple Frequency CountsJanuary 13th, 2016 Patrick Stein

The first coding assignment of the Data Management and Visualization class that I am doing on Coursera is just to do some frequency analysis on some of the variables that will be involved in the research you want to do.

I am using the 2012 U.S. Presidential Election data broken down by county.

### Frequency Counts

The assignment was to do frequency counts. If I did tables of raw frequency counts, the tables would be huge. There are 4588 counties in the data set. There are 4075 different values for the total number of votes cast in a county. As such, I bucketed the counts based upon the power of ten of the value. Here is the output for the total number of votes cast:

+----------------+--------------------+
|    Votes Total | Number of counties |
+----------------+--------------------+
|            1's | 3                  |
|           10's | 72                 |
|          100's | 646                |
|        1,000's | 2102               |
|       10,000's | 1513               |
|      100,000's | 247                |
|    1,000,000's | 5                  |
+----------------+--------------------+
NIL

Here is the output for the total number of votes for Democratic candidates and for the Republican candidates:

CL-USER> (print-log-buckets "Dem" #'vote-distribution-dem)
+----------------+--------------------+
|      Votes Dem | Number of counties |
+----------------+--------------------+
|            1's | 15                 |
|           10's | 166                |
|          100's | 1171               |
|        1,000's | 2380               |
|       10,000's | 730                |
|      100,000's | 124                |
|    1,000,000's | 2                  |
+----------------+--------------------+
NIL
CL-USER> (print-log-buckets "GOP" #'vote-distribution-gop)
+----------------+--------------------+
|      Votes GOP | Number of counties |
+----------------+--------------------+
|            1's | 12                 |
|           10's | 171                |
|          100's | 937                |
|        1,000's | 2349               |
|       10,000's | 1009               |
|      100,000's | 110                |
+----------------+--------------------+
NIL

With the above frequency count, we can see that of the five counties with over a million votes cast, the Democrats got more than a million votes in two of them whilst the Republicans did not get a million votes in any county.

The numbers are pretty close the whole way through, but that still doesn’t mean a great deal. It could be that the fifteen counties where Democrats got fewer than ten votes were counties with ten thousand votes cast. So, I put together a small function then to get the worst counties for a given party:

(defun get-worst-counties (key &optional (how-many 10))
(subseq (stable-sort (copy-seq *by-county*)
#'<
:key (lambda (dist)
(/ (funcall key dist)
(max 1
0
how-many))

The worst counties for Democrats and Republicans?

CL-USER> (get-worst-counties #'vote-distribution-dem)
(#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "HANCOCK CTY TOWNSHIPS" :DEM 0 :GOP 0 :VOTES-CAST 0)
#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "UPTON" :DEM 0 :GOP 0 :VOTES-CAST 0)
#S(VOTE-DISTRIBUTION :STATE "TX" :COUNTY "KING" :DEM 5 :GOP 139 :VOTES-CAST 145)
#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "MORO PLT." :DEM 1 :GOP 21 :VOTES-CAST 23)
#S(VOTE-DISTRIBUTION :STATE "MT" :COUNTY "WIBAUX" :DEM 25 :GOP 421 :VOTES-CAST 544)
#S(VOTE-DISTRIBUTION :STATE "TX" :COUNTY "ROBERTS" :DEM 25 :GOP 408 :VOTES-CAST 439)
#S(VOTE-DISTRIBUTION :STATE "ID" :COUNTY "FRANKLIN" :DEM 325 :GOP 5195 :VOTES-CAST 5600)
#S(VOTE-DISTRIBUTION :STATE "TX" :COUNTY "STERLING" :DEM 31 :GOP 459 :VOTES-CAST 494)
#S(VOTE-DISTRIBUTION :STATE "TX" :COUNTY "GLASSCOCK" :DEM 44 :GOP 526 :VOTES-CAST 578))
CL-USER> (get-worst-counties #'vote-distribution-gop)
(#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "HANCOCK CTY TOWNSHIPS" :DEM 0 :GOP 0 :VOTES-CAST 0)
#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "UPTON" :DEM 0 :GOP 0 :VOTES-CAST 0)
#S(VOTE-DISTRIBUTION :STATE "SD" :COUNTY "SHANNON" :DEM 2922 :GOP 188 :VOTES-CAST 3130)
#S(VOTE-DISTRIBUTION :STATE "CT" :COUNTY "HARTFORD" :DEM 31735 :GOP 2138 :VOTES-CAST 34037)
#S(VOTE-DISTRIBUTION :STATE "DC" :COUNTY "DISTRICT OF COLUMBIA" :DEM 222332 :GOP 17337 :VOTES-CAST 243348)
#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "PENOBSCOT NATION VOT DST" :DEM 253 :GOP 23 :VOTES-CAST 281)
#S(VOTE-DISTRIBUTION :STATE "NY" :COUNTY "BRONX" :DEM 288378 :GOP 26304 :VOTES-CAST 316047)
#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "ISLE AU HAUT" :DEM 48 :GOP 5 :VOTES-CAST 57)
#S(VOTE-DISTRIBUTION :STATE "MA" :COUNTY "PROVINCETOWN" :DEM 2121 :GOP 210 :VOTES-CAST 2380)
#S(VOTE-DISTRIBUTION :STATE "ME" :COUNTY "MONHEGAN PLT." :DEM 49 :GOP 5 :VOTES-CAST 55))

As you can see from this, there are two counties which show no votes cast. In both of those cases, there are no precincts reporting in the data set. The data set tells the number of precincts in the county along with the number of precincts reporting. These counties with none of the precincts reporting are significant glitches in the data. On the other hand, some counties in the data have hundreds of precincts where all but one reported. I could remove a county from the data if not all of its precincts reported. However, I believe that within a county, single precincts will not differ very much from other precincts which were counted in the data. Further, as I do not have any hope of determining the population density down to the precinct level, I am just going to roll with what I have.

### Implementation

I put together some simple utilities around Fare-CSV to retrieve particular columns of a CSV file formatted in particular ways. Here is the source code for those utilities.

One of the things that immediately became apparent is that there are two separate columns in the database labelled `"TOTAL VOTES CAST"`. I wanted to make sure there were no confusion, so I wrote a quick function then to check that both of those columns agree everywhere.

(let ((columns (find-columns-with-label "TOTAL VOTES CAST")))
(apply #'= (get-columns-as #'parse-integer-allowing-junk
columns))))

Spoiler: They do. Whew!

The data here has one row per county. I might have preferred there be one row per county/candidate pair. Regardless, I wrote a short function that takes a party name and all of the columns identifying parties along with the columns identifying how many votes a given party received.

(loop :for p :in parties
:when (string= p party)
:sum v))

For example, this might get arguments party = `"DEM"`, parties = `("DEM" "GOP" "LIB" "GRN" "" "" "" "" "" "" "" "" "" "" "" "")`, and votes = `(91696 121234 5539 2127 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)`. This function sums up all of the numbers in the votes list where the corresponding entry in the parties list matches the given party.

I made a little data structure to hold the data that I am interested in for each county.

(defstruct vote-distribution
(state "" :type string)
(county "" :type string)
(dem 0 :type integer)
(gop 0 :type integer)

I then created a function which returns a function. The returned function returns an instance of my data structure for the row passed into it. Note: the data set contains rows which roll-up the results for a whole state. For those rows, the FIPS code for the county is zero.

(let ((state-column  (find-column-with-label "State Postal"))
(county-column (find-column-with-label "County Name"))
(fips-column   (find-column-with-label "FIPS Code"))
(party-columns (find-columns-with-label "Party"))

(lambda (*row*)
(when (plusp (get-column-as #'parse-integer-allowing-junk fips-column))
(let* ((state (get-column-as #'string-upcase state-column))
(county (get-column-as #'string-upcase county-column))
(total (get-column-as #'parse-integer-allowing-junk
total-column))
(parties (get-columns-as #'string-upcase party-columns))
(make-vote-distribution :state state
:county county

I did that because I originally had all of that functionality in the function which loops over each of the rows in the data set. Now, the function that collects all of these is simpler, but I’m not sure the overall simplicity is much improved.

:for row :in (data-rows)
:for dist := (funcall collector row)
:when dist
:collect dist))

(defparameter *by-county*
#'<

I created a function to bucket them based on their base-10 logarithm. Of course, this immediately freaked out on the couple of counties for which there is no data in the data set, so I had to take care not to take the logarithm of zero.

(let ((buckets (make-hash-table :test #'equal))
(max-bucket 0))
(labels ((bucket-number (dist)
(floor (log (max (funcall key dist) 1)
10)))
(incorporate (dist)
(let ((n (bucket-number dist)))
(setf max-bucket (max n max-bucket)
(gethash n buckets) (1+ (gethash n buckets 0))))))
(mapc #'incorporate *by-county*)
(loop :for n :to max-bucket
:collect (gethash n buckets 0)))))

I made a wrapper function for that which pretty-prints the results as a table.

(defun print-log-buckets (label &optional (key #'vote-distribution-votes-cast))
(let ((buckets (loop :for pow :from 0
:for buck :in (log-buckets key)
:appending (list (expt 10 pow) buck))))
(format t "+~16,,,'-<~>+~20,,,'-<~>+~%")
(format t "|~16< Votes ~A ~>| Number of counties |~%" label)
(format t "+~16,,,'-<~>+~20,,,'-<~>+~%")
(format t "~{| ~12:D's | ~D ~38T|~%~}" buckets)
(format t "+~16,,,'-<~>+~20,,,'-<~>+~%")))