Hacker News new | ask | show | jobs
by yewweitan 5685 days ago
I'd say Common Lisp is the superior choice.

In terms of the availability of support libraries and what not, you'll find it easier with Common Lisp. Quicklisp would be the most recent (and awesome) tool that comes to mind.

In terms of the language itself, it's just more complete to me.

LET and LET* have very different uses, and while ugly, LABELS has helped me quite a fair bit, especially in porting over some recursive Haskell code.

Oh, and don't forget the wonders of LOOP =)

Other than that, I can't speak for Racket, nor any of the other Lisps out there. So take by biased opinion as a CL user for what its worth.

2 comments

Why do you say LET and LET* have very different uses? I just use LET* if I need to reference a preceding variable in the same declaration (it happens). Actually I vaguely remember PG in one of his Lisp books saying LET* indicates bad code, something I never understood, though empirically I've noticed some evidence for it.
Well, maybe 'very different' was an overstatement =).

One way to look at it is that we should use single-use functions as far as possible to keep code straightforward.

And as jpr said, LET* can potentially promote bad style, giving one the inclination to mix functional and imperative styles in a potentially troublesome fashion.

I think it was in 'On Lisp' that PG said that use of LET* should be minimised for the reasons above.

But if not, you're right. Use LET* just as you mentioned, but don't use LET* for all cases.

Some discussion available @ Stack Overflow: http://stackoverflow.com/questions/554949/let-versus-let-in-...

> LET* indicates bad code, something I never understood

Neither did I, until I encountered something along the lines of:

    (let* ((foo ...)

           (foo ...)

           (foo ...)

           (foo ...)

           (foo ...)

           (foo ...)

           (foo ...))

        ...)
That's strangely unidiomatic. I wonder why that person didn't just write:

  (let ((foo ...))
    (setf foo ...)
    (setf foo ...)
    ...)
On a tangential note, while I try to avoid multiple assignment as much as possible, I also enjoy availing myself of CL's imperativeness whenever doing so makes my code smaller or more efficient. I really like CL's multiparadigm approach. The sweet spot seems to be: allow side-effects in the small (i.e. within functions or small scopes) and be as strict as you can in composing larger pieces.
LOOP is awesome, probably my favorite feature of Common Lisp after CLOS.