Lisp Style

Some followup from my previous post on Lisp…

— Lisp Resources —

The book "Practical Common Lisp" is available online, published by the author in its entirety.

Also, a CS professor Slava Akhmechet wrote an essay in the same vein, translating from C++ to Lisp — via Xml of all things. 

(In full disclosure, I’ve *never* seen the light of Xml, and verbally abuse it at every opportunity even if only in a hush tone.  It’s like a reflex.  But more people these days are familiar with Xml trees, and the essay is well written).

— Lisp Style —

Also, I’ve noticed I’ve gotten Lisp style wrong slightly.  It is also common to indent to align with the name of the function or language construct being invoked.  This might look like:

   (defun fib (n)
          (if (< n 2)
              1
            (+ (fib (- x 1))
               (fib (- x 2)))))

Note the left paren aligning bellow to the right of ‘defun’, and ‘1’ aligning to the right of ‘if’.  The lesser indent for the ‘+’ operation is used to distinguish the ‘else’ clause for the programmer. 

Don’t align incorrectly:

   ; this code lies!  the programmer incorrectly
   ; aligned 'do-something', which is part of the
   ; addition expresion
   (if (xyz 1 (* 2 3)
       (do-something))
       (something-else))

Instead:

   ; much better.  now it's clear that 'do-something'
   ; is part of the condition expression
   (if (xyz 1
            (* 2 3)
            (do-something))
       (something-else))

There’s even a Lisp plugin for SlickEdit (my code editor of choice) that will automatically adjust the indent for you, as well as add other editor support, and I hear that Emacs has equally great Lisp editing support.

Memoizer 4a – Lisp for Mortals

Now that this is getting to be a series, I ought to provide links to the previous entries, in case anyone is actually reading this thing:

Other than the C++ example, this series has been part of an experiment to bootstrap my experience in dynamically typed programming languages — and what sort of experiment would it be if I overlooked Lisp.  So here it goes.

All those parenthesis!

I can already hear the cries of some programmers, those who were brought up being told Lisp is interesting, but full of all those inscrutable (((parenthesis))) that make it so hard to read.  I know because I feel the same way — like many others, I come from C and initially fear the parenthesis.

So, to get that out of the way, Lisp parenthesis 101!

In Python, you might write:

  1:     # python, step 0
  2:     def fib(n):
  3:       if n < 2:
  4:         return 1
  5:       else:
  6:         return fib(n-1) + fib(n-2)

Or better yet, In C and C++ you might write:

  1:     // C++, step 0
  2:     int fib(int n){
  3:       if(n < 2) {
  4:          return 1;
  5:       } else {
  6:         return fib(n-1) + fib(n-2);
  7:       }
  8:     }

Lets start translating it to Lisp.

Step One: remove those types in the function signature in C, and replace the Python ‘def’ with ‘defun’:

    # python, step 1
    defun fib (n):
      if n < 2:
        return 1
      else:
        return fib(n-1) + fib(n-2)
    // C++, step 1
    defun fib (n) {
      if(n < 2) {
         return 1;
      } else {
        return fib(n-1) + fib(n-2);
      }
    }

Step Two: Lisp takes away operators, and gives you back consicely named functions.  Pretend that “+” and “<” are simple functions, so “x < y” can be reworded “<(x, y)” and so forth.

    # python, step 2
    defun fib (n):
      if <(n, 2):
        return 1
      else:
        return +(fib(-(n,1)), fib(-(n,2)))
    // C++, step 2
    defun fib (n) {
      if( <(n, 2) ) {
         return 1;
      } else {
        return +(fib(-(n,1)), fib(-(n,2)));
      }
    }

Step Three: Lets replace curly braces {} and indenting with parenthesis. And for good measure, lets put those function names inside the parenthesis so we can always tell which thing is getting which arguments:

    # python, step 3
    (defun fib (n):
      (if (< n 2):
        (return 1)
      else
        (return (+ (fib (- n 1)) (fib (- n 2))))))
    // C++? step 3
    (defun fib (n)
      (if (< n 2)
        (return 1);
      else
        (return (+ (fib (- n 1)) (fib (- n 2))));
      )
    )

Step Four: Now we’re in the home stretch. Those semicolons are just getting in the way now, and I’ve already ripped out the commas from underneath you.  The keywords ‘else’ and ‘return’ are superfluous now.  A little more cleanup, and:

    ; Python-y Lisp! step 4
    (defun fib (n)
      (if (< n 2)
          1
        (+ (fib (- n 1)) (fib (- n 2)))))
    ; C++-y Lisp! step 4
    (defun fib (n)
      (if (< n 2)
          1
        (+ (fib (- n 1)) (fib (- n 2)))
      )
    )

Now the only difference we’re left with is indentation.  C++-y Lispers may want to keep with the closing-brace style above, but Scheme Style would suggest the whitespace/Python-like approach.

Until next time…

I only picked up Practical Common Lisp just today, and this post is long enough as it is, so I’ll save the memoizer for the next post.

Whether you love Lisp or hate it, I hope this post can help you see past all those (((parenthesis))).

Your Favorite PL

In your favorite programming language

I came across this site, hanoimania, when researching application virtual machines.  The author, personally, has translated a towers of hanoi solver to dozens of programming languages, utilizing:

Although, the embedded world uses the ARM architecture more often these days. 

Reminds me of 99 Bottles.

50 in 50

Lastly I’ve been ranting and raving about 50 in 50 from last month, where Guy L Steele Jr. and Richard P. Gabriel gave a sort of artistic performance — 50 statements of 50 words on programming languages.  I’m still looking up historical references from this thing! 

From the performance:

Alt text: We lost the documentation on quantum mechanics. You’ll have to decode the regexes yourself.