Struggling to Keep the Faith April 11th, 2015
Patrick Stein

Six years ago, I wrote about how the choice of programming language dramatically affects the way in which I write code. In that post from six years ago, I said:

In Lisp, I will pull something out into a separate function if it makes the current function more self-contained, more one idea. In C++, I will only pull something out into a separate function if I need the same functionality in multiple places.

At the moment, I’m getting paid to write in C++ for the first time in two years (technically, I suppose I did write some small C++ sample code in my previous job, too). I am struggling at the moment to make my C++ functions as small as I would have made them if I were writing in Lisp.

There are obvious barriers to this imposed by C++. While one of the projects at my work is converting a large swath of code to C++11, my project is still stuck on C++98. This means that I can’t use lambda functions, auto, or for-each style for loops and that I can’t get away with letting the compiler figure out my template types in almost any situation.

For instance, I have one function that is about twenty lines of comments and ten lines of code comprising exactly three statements. Three statements took ten lines of code because when you want to use a pointer to a member function in a std::count_if call, you need to jump through about a hundred characters of declarations and syntax to turn the pointer to a member function of one argument into a regular function of two arguments (using std::mem_fun1_t) and another pile of characters to turn it into a regular function of one parameter again (using std::bind1st). And, I spent nearly an hour trying to glark the type I’d have had to declare in one of the intermediate steps to turn those three statements into four instead. I gave up.

bool MyClass::attemptToFrob( item_t& item )
  return item.frob( _frobRetryCount, _frobTimeoutValue );

bool MyClass::frobAllOfMyItems()
  return performItemOperationOnAllItems( &MyClass::attemptToFrob );

bool MyClass::performItemOperationOnAllItems(
                bool (MyClass::*op)(item_t&)
  std::mem_fun1_t<bool,MyClass,item_t> binOp(op);
  unsigned int successes = std::count_if( _items.begin(),
                                          std::bind1st( binOp, this ) );
  return ( _items.size() == successes );

In C++11, I’d have written the function as two statements, only one of which had to span more than one line to stay under 80 columns. In C++0X, I’d at least have been able to auto an intermediate statement to hold the result of std::bind1st that I couldn’t manage to satisfy myself.

I really believe that trying to keep the functions down to three or four lines with at most one conditional is a goal that goes a long way toward readability. But, man, it sucks for writability when you’re stuck in a strongly-typed language with a compiler that isn’t at all interested in helping you out with that.

And, a pet peeve here while I’m already ranting about C++…. Am I right in believing that neither C++98, C++0X, C++11, or C++14 have any way to iterate over the keys of a std::map or to wrap a function of one argument that takes a pair and just uses the first half of the pair to invoke the original function? Something like this:

template <class R, class T, class U>
class call1st {
  call1st( R (*fn)(T) ) : _fn(fn) {};
  R operator ( std::pair<T,U>& p ) { return (_fn)(p.first); };
  R (*_fn)(T);

Most of why I would want this would be more clear with lambdas instead. But, if there is still going to be crap in the language like std::mem_fun1_ref_t and such, why is there still no functional way (in the #include <functional> sense) to get to the members of a pair? Or, I am just missing something obvious?

Trying Clojure again? March 26th, 2015
Patrick Stein

EDIT: Indeed, as people on Reddit pointed out, installing Lein is simply downloading a script and running it. Installing CIDER from MELPA was also easy. The two, however, aren’t completely compatible at the moment because CIDER from MELPA wants nREPL 0.2.7 at least and Lein only pulls in 0.2.6 (even though, I believe the current is 0.2.10).

It has been five years since I last tried Clojure. I feel like I should try it again.

I don’t want to beat my head against Leiningen for even ten minutes this time. Is there some way to reasonably use Emacs + Clojure without have to install and configure CLASSPATHS and Mavens and Ants and JDKs?

It seems SWANK-CLOJURE has been deprecated in favor of CIDER. The CIDER doc says how to configure Leiningen or Boot for use with CIDER. Is there some way that I can avoid Leingingen and Boot? Or some way that I can click one ‘Install’ button and have Leiningen and Boot work?

Braille chords Emacs minor mode February 11th, 2015
Patrick Stein

I have been reading and writing a fair amount of Braille lately. Duxbury Systems has an excellent cheat sheet which outlines the different abbreviations used in Grade 2, English Braille. This is a great help to me when I am writing, but it is organized poorly for reading.

I started making myself an inverted version of that cheat sheet, but was quickly frustrated trying to type Braille on my QWERTY keyboard. What to do? I wrote some Emacs lisp code to allow me to type Braille characters into Emacs in the same, chorded manner that one would enter them on a Braille keyboard.

You can find the code on github: braille-chords.el. The documentation is comments at the top of the source file.

Cons-Air (a.k.a. Lispers On A Plane) January 22nd, 2015
Patrick Stein

Before bed last night, I was trying to sort out in my head the lineage and historical inter-relations between BKNR, TBNL, HTML-TEMPLATES, CL-WHO, and Hunchentoot. When my alarm went off this morning, I was having a dream about the Lisp community.

In my dream, there were about 50 Lispers on a prison plane. It was pretty much a commercial 737, but all of the passengers were wearing prison jumpsuits and the plane would never land. We were all just on the plane. We refueled in flight. (The dream had nothing to say about how we restocked with food or emptied the septic tanks. *shrug*)

There was a cage around/over the last three rows of the left side of the plane. The door to the cage was not locked, but everyone knew that you were only allowed to go into the cage if Edi let you. Edi Weitz was the top dog in this prison. The only reason the rest of us were still alive is because Edi hadn’t seen a reason to have us taken care of yet.

Didier Verna was the only person who was allowed to approach the cage if Edi were in it.

There wasn’t much turbulence, but we were flying through a thunderstorm. This had Nick Levine sitting at a window seat, looking out over the wing, nervously bobbing back and forth, and sipping whiskey with ice from a plastic cup.

The storm had Zach Beane pacing back and forth in the aisle.

Cyrus Harmon was sitting doing a crossword puzzle from the in-flight magazines, giggling to himself about Faré.

Faré was standing near the front of the plane throwing little packets of peanuts at everyone. He wasn’t trying to hurt people with them, but he was delighting in watching them bounce of the heads of people who weren’t expecting them (especially the back of Zach’s head when he was fifteen or twenty rows away).

Robert Goldman was trying to get some sleep, but was unable to do so because of the lack of leg-room, the bright cabin lights, and all of the packets of peanuts careening past.

There were a number of other Lisp-folk in this dream. For some of them, I don’t recall exactly what they were up to. For a few, it would probably be impolitic of me to say. :)

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
     "Always pick the letter A."

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

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

Updates In Email