Monthly Archives: March 2014

tidy up the output of lisp macros

For some reason it makes my teeth hurt to have my macros generate code that I wouldn’t have written by hand.  For example it’s not hard to get code like this out of a macro expansion.

(let ()
  (progn
    (if (fp x)
      (progn 
         (f1 x)
         (f2 x)))))

v.s. what I might like:

(when (fp x)
   (f1 x)
   (f2 x))

I probably ought to just relax and ignore it, but instead I often revise macros so the code they generate is nicer to look at.   So that:

`(let ,vars ,@body)

becomes

(if vars
    `(let ,vars ,@body)
    `(progn ,@body))

This is silly!   Now I have ugly macros instead of ugly output.   I’m just moving the ugly bits around.

So I’ve started doing this:

(tidy-expression `(let ,vars ,@body))

where tidy-expression is something like this:

(defun tidy-expression (x)
  (match x
    (`(or ,a (or ,@b)) `(or ,a ,@b))
    (`(progn ,a (progn ,@b)) `(progn ,a ,@b))
    (`(progn ,x) x)
    (`(and ,a (and ,@b)) `(and ,a ,@b))
    (`(if ,a (progn ,@b)) `(when ,a ,@b))
    (`(if ,a (progn ,@b) (progn ,@c)) `(cond (,a ,@b) (t ,@c)))
    (`(if ,a (progn ,@b) ,c) `(cond (,a ,@b) (t ,c)))
    (`(if ,a ,b (progn ,@c)) `(cond (,a ,b) (t ,@c)))
    (`(let ,vs (progn ,@body)) (tidy-expression `(let ,vs ,@body)))
    (`(let nil ,@body) (tidy-expression `(progn ,@body)))
    (_ x)))

It’s another chapter in my crush on optima.

I write these tidy up functions as necessary.

That example only chews on the top of the form.   If you wanted something to clean up the first example you’d need to write tidy-expression-all.

(tidy-expression-all
 '(progn
   (if (fp x)
       (progn 
         (f1 x)
         (f2 x)))))
-->
(when (fp x) (f1 x) (f2 x))

This all reminds me of Warren Teitelman’s programmer’s assistant in Interlisp.  It reminds me of some of the things that flycheck in Emacs does for other programming languages.   It reminds me that I’ve been wondering what would a lint for Common Lisp would look like.

I bet somebody already wrote a generalized tidy expression and I just don’t know were to look.

Inviting Disaster

James Chiles’ “Inviting Disaster: Lessons from the Edge of Technology” is a fun read, except that it’s a spoiler for the books that tells the story of just one of these disasters.  The best part of the book, and the part you never get in books like this and certainly not in the books about a single debacle, is a section where he tells a few stories about people doing the right things to avoid the horrible outcome.

I particularly liked learning that Nobel had so much trouble getting with workers smuggling matches into the factory that finally he started making them strip naked each morning and walk thru a pool up to their neck.

It disappoints in some ways: there are no financial disasters and no software disasters.  There are no examples of failures of collective action or public good management, i.e. levee failures.  Or for that matter catastrophes caused by a the false sense of security that comes from gradual processes.

Since it’s mostly stories it is not a very useful book if you want to learn what makes dangerous systems and what to do about it.  Normal Accidents remains a good starting point for that.  But stories are fun, and very useful.  Everybody ought to read a few of the books on this shelf in the Library.

Oh, and don’t try to extinguish a fire by flooding the cargo hold with steam when it’s loaded with fertilizer.

Lint for your shell scripts!

ShellCheck will critique your shell scripts, i.e. it’s a static checker for Bash etc.  You can try it online at shellcheck.net.  You can also install it on your own machines.

If you combine it with emac’s flycheck it is particularly delightful!

I had trouble installing it locally.  I believe this recipe works.  It’s written in Haskell, so first your install Haskell’s package manager cabal.  I used brew cabal-install.  Then do cabal update.  At that point you clone shellcheck from github (git clone https://github.com/koalaman/shellcheck.git) and cd into the resulting directory cd shellcheck and run cabal install. Sometime later ~/.cabal/bin/shellcheck appears, and you can set flycheck-sh-shellcheck-executable so flycheck can find it.

Wolfram Alpha

Watching these into to Wolfram Alpha videos (for example) give me a certain arousal that I have experienced only a handful of times.  The first time was when I discovered the APL prompt hidden inside the Dartmouth Basic CLI on the Teletype in high school.  Then there was Focal on the PDP-12 which let you draw charts on the machine’s CRT.  Latter there was discovering that I could run Mathematica at MIT over the Arpanet from CMU.  And, of course, the Lisp Machine.  I don’t know what it is about these systems that gets me excited.  R, Prolog, Erlang, Emacs all got close but never managed to trigger this curious arousal for me.

Wolfram Alpha is a lovely example of what is now possible.  The Lisp Machine was so very similar, particularly with its UI, to what that demos is showing.  But what’s new is the amount of data and algorithms we can now bring to bear.  Where are the engineering stations that treat the entire web’s as a reasonably well-organized dataset?  That is/was the RDF fantasy.  It’s nice to see it starting to pop-up up.

Of course it’s unlikely that I’d invest a lot in climbing the learning curve of a system like this, given that it’s proprietary.

Update: Article in Slate, and a classic on Wolfram’s ego and many other flaws.

,@ v.s. ,.

I’m surprised that I didn’t know about the ,. construct in Common Lisp’s backquote syntax.  It is equivalent to ,@ except that it licenses the implementation to destructively modified the tail of the list being inlined.

cl-user> (defparameter *x* '(1 2 3))
*x*
cl-user> *x*
(1 2 3)
cl-user> `(a b ,@*x* c d)
(a b 1 2 3 c d)
cl-user> *x*
(1 2 3)
cl-user> `(a b ,.*x* c d)
(a b 1 2 3 c d)
cl-user> *x*
(1 2 3 c d)
cl-user>