HYPERTHINGS

An Ode To LOOP


A Hidden Lesson in Lisp Style

LOOP: the venerable iteration construct in Common Lisp. Much maligned, much loved, and much to teach. A short post.

An Ode

       Thou still unresting ox of programming  
         Thou working dog of Lispers who control  
       Pithy key phrases that make expressing  
         Iterations diverse so much less dull  
       What brain-mad coder taunts about thy faults  
         of extension or learning, or of both,  
            on Reddit or the sloughs of Planet Lisp?  
         What noobs or frauds are these? Why do they loathe?  
       What argument might prompt their swifter halt?  
            Can I convince with 'passioned words so crisp?  
     

With apologies to the ghost of Keats

A LOOP EXPRESSION

Consider the following LOOP expression, and keep this example in mind as you peruse the rest of this post.

      (loop  
        for name being the hash-key of person-table  
        for person being the hash-value of person-table  
        for iterations from 0  
        when (string-equal name "larry")  
          collecting person into larrys  
          and do (format t "Hi, I'm ~a~%" (full-name person))  
        when (string-equal name "darryl")  
          counting name into darryls-count  
        while (< darryls-count 1000)  
        finally (return (values larrys darryls-count iterations))) 

Just reading it, do you have an idea about what it is doing?

It seems to be looping over a hash table and doing the following things:

  1. Keeping a running total of the number of iterations so far.
  2. collecting a list of persons named "larry" and storing it in variable called larrys.
  3. Additionally, for each such Larry, print their full name.
  4. counting the number of people named "darryl" that occur, and storing that count as darryls-count.
  5. But only doing all of the above so long as we've seen fewer than 1000 Darryls.
  6. finally, we return several values, the list of Larrys, the number of Darryls, and the total number of interations.

LOOP has some defects, some boons, and some lessons to teach.

DEFECTS

LOOP sucks because of ...

  1. Extensibility: it cannot be used to iterate over exotic data containers. Just ranges, lists (in two ways), vectors, and hash tables.
  2. Lispiness: it doesn't look like the rest of Common Lisp. Note the relative lack of parentheses in the above!
  3. Superfluity: it is an entire extra language unto itself, with hard-to-recall keywords and syntax. E.g. being the hash-key of ....

BOONS

But LOOP is great because of ...

  1. Versatility: Even though it isn't extensible, it is still pretty darn versatile. With LOOP you can collect,append count, sum, maximize, minimize; you run code when or unless or while or until some condition is true; you can check that a condition is always or never true, or that thereis at least one true instance of the condition; you can define local variables, pattern match on binding forms, and iterate over most built-in data structures; and on and on...
  2. Readability: Despite feeling odd, LOOP expressions are fairly descriptive of what they're doing. If you have even a passing familiarity with programming, then you can probably figure out what the above does. It reads almost like psuedocode.
  3. Performance: Iterating with LOOP is frequently quite fast. Expressions expand into highly imperative code that uses BLOCK, TAGBODY, GO, and SETQ. In other words, the extra language is worth the trouble to learn because it generates fast code with less typing. The above expression, for example, expands into roughly 70 lines of lower-level Lisp.

LESSONS

LOOP is typical of Common Lisp style as a whole. By "style" I do not mean what code looks like in your editor. Instead, by "style" I mean the way that Lispers approach problem solving, and the way that Lispers approach Lisp itself.

LOOP has lessons to teach about Lisp Style:

  1. Just to prove how good Lisp is for defining DSLs, one is included in the standard! From this I learned that sometimes a new language makes some domains easier to work in.
  2. LOOP's limitations motivated many Lispers to extend the language, a very Lispy practice indeed. From this I learned that it is totally appropriate to extend Lisp to meet my needs.
  3. LOOP provides further evidence that Lisp is a truly multi-paradigm technology, one that that embraces practicality. That is, LOOP may stand out, it may seem impure, but it is a practical tool for implementing loops. From this I learned to stop worrying about purity in favor of doing what works.

WRAP-UP

LOOP may not be extensible, but Lisp sure is. Try one of iterate, for, or series if you need to loop over exotic containers.

LOOP syntax may not be immediately obvious, but there are loads of great resources for learning to LOOP.

Keep on hacking!

-colin