Programming ≈ Fun

Written by Krešimir Bojčić

What's Special About Lisp?

One thing that bothers me with Lisp is that I can’t seem to find example of this alleged superiority of the S-expression way. I get the flexibility that you can gain by using macros and defining language on the fly, but it looks to me this is not as important as it might seem.

  • You can fake it anywhere else with more or less work
  • Idea is the main problem, not the elegance of future solution
  • When you are not “smart” you work harder to compensate - that is usually enough (just check out Russian vs. German tactic about producing tanks in WW2)

Best answers about using macros I was able to find was: look in Lisp you can do thing like RSpec in 20 minutes. My point is that I have that in Ruby. I know it might not be as elegant as in Lisp but if someone else does the hard work to bring me DSL that I need, what is advantage of doing it myself. The problematic part of RSpec was idea. I would never think of such a great idea in the first place. Coding of it is irrelevant.

Every time I interview people for job, I ask them to show me what they have done. In Lisp I get a feeling that nothing was done since ‘58. Let’s take Perl for example, it arguably looks terrible(cryptic to be nice about it), but you have CPAN that is evidence that

  • people use it
  • you can get things done in it

I took example from Practical Lisp about building do-primes macro. I know the counter argument will be that this is just stupid example, but that’s my point I can’t seem to find good enough example anywhere. I am reading one of top tree Lisp books, and examples are reachable from my unworthy language. BTW. Practical Common Lisp is a great book.

(defun primep (number)
  (when (> number 1)
    (loop for fac from 2 to (isqrt number)
      never (zerop (mod number fac)))))

(defun next-prime (number)
  (loop for n from number when (primep n) return n))

(defmacro do-primes ((var start end) &body body)
  `(do ((,var (next-prime ,start) (next-prime (1+ ,var))))
       ((> ,var ,end))
     ,@body))

That enables you to extend the language and use it like this:

(do-primes (p 0 20)
 (format t "~d " p))

2 3 5 7 11 13 17 19

All that is pretty nice but I am not all that impressed. You can easily do this is Ruby:

def prime_number? (number)
  number > 1 and not (2..Math.sqrt(number)).find{ |n| number % n == 0 }
end

def do_primes(a, b, &block)
  (a..b).each { |number| block.call(number) if prime_number? number }
end

Usage would be:

do_primes(0, 20) { |x| print "#{x} " }

To take it step further let’s extent build in Range class and make it OO

class Range
 def primes
   select{ |n| prime? n }
 end

private
 def prime?(number)
   number > 1 and not (2..Math.sqrt(number)).find{ |n| number % n == 0 }
 end
end

Usage would be:

(1..20).primes.each { |x| print "#{x} " }
print (1..20).primes

Now that seems like nice and natural extension of a language if I need it. (But I don’t and that’s the reason it is not already present). I think somebody on Joel forum got this right about people not liking it and not working in it not because they don’t get it but because they choose not to: LISP sucks. This is also interesting point of view The Bipolar Lisp Programmer about culture in Lisp.

EDIT: This got some tremendous feedback and to be honest it is way over my league. Thanks for the discussion. I think post should have been titled “Is Lisp Special Enough?”. In theory you got this beautiful homoiconicity, you are at the root and you can do with AST whatever you need. As we all know theory and practice are same only in theory.

In practice you have a language designed/discovered to build libraries and not so many libraries compared to the rest. Is it because people are stupid and just not getting it, or because people just don’t like it and choose to do it other ways? I think it is the second reason. It seems bold to claim that people that made different choice are dumber in any way especially if they have better track record. In Ruby you can do wonders with implicit DSL, little eval and blocks. If you need something stronger what is so unpure about making external parser. Is there really that many uses that justify so much flexibility Lisp provides (and nothing comes for free in life, so to be 100% flexible you have to loose somewhere else).

I don’t think Ruby is about being popular, sure it might hit mainstream because it’s good enough, but I like it because it’s fun. Also I don’t think Lisp was even all that special before Ruby/Python etc. We have Smalltalk since late seventies. Smalltalk contains pretty much all of stuff that makes Ruby cool today.

Thanks for provided links, and improved Ruby code. I will make sure to checkout examples of real life Lisp macros, and as I said in one of my comments I have great respect for Clojure.

For extensive Common Lisp guide you might want to check out this awesome site.

Comments