
Common Lisp - Myths and Legends - fogus
http://www.lispworks.com/products/myths_and_legends.html
======
hvs
I love CL. Absolutely love it. But these sorts of articles (this one is
actually quite a few years old) just depress me. It's as if every one who
defends CL has to make these sorts of "It's only a flesh wound!" sorts of
arguments. With all deference to PG, one web application in over 10 years does
not an argument make. Like I said, I love CL, I use CL, but it is not a
popular language and I can't blame any company that chooses to go with Python
or Ruby simply due to inertia of the languages.

And don't get me started on how you are supposed to decide how to choose an
implementation of CL...

~~~
gaius
The annoying thing is, I can't use LispWorks with an RDBMS unless I pay for
the Enterprise Edition. So I can't even do a pilot project without it being
"official" within the company. So there is zero possibility of a grassroots
adoption happening.

Contrast this with Oracle. One of the most money-obsessed companies in the
world, I'm sure we'd all agree. But you can download Oracle Enterprise Edition
for free with zero fuss and kick the tyres. They don't care, no time limit or
size limit or anything, until you go into production with it.

~~~
mahmud
You can't also access an RDBMs from C without paying for Visual Studio
Enterprise Edition, _or_ using any of the myriad of Free compilers out there
that are much better anyway, which everyone else uses.

------
edoloughlin
Here's something that's not a myth or legend: if I live in Europe I pay ~€150
more for the professional version than I would if I lived in the US.
(<http://www.lispworks.com/buy/prices-1c.html> vs
<http://www.lispworks.com/buy/prices-2c.html>)

~~~
jrockway
SBCL + Emacs probably has more features and runs faster anyway.

------
kruhft
I've been taking some time to learn CL lately, and one of the things I've been
doing is SPOJ (<http://www.spoj.pl>) problems. One one paticular problem
(FCTRL) I attempted to solve it in CL and came up with code that I was pretty
sure would work. After submitting a number of times using the SBCL compiler, I
could not solve the problem in the time allocated.

So I went off and just manually translated my code to Python. Exact same
algorithm, pretty much word for word translation. Submitted, and made the cut
(barely).

This I found dissapointing; how could a byte code interpreted language be
faster than a compiled language?

So I picked up 'ANSI Common Lisp' and started optimizing. Found some problems
where I was using / instead of when I could just use floor (but then I found a
problem where floor always does a cons; why is there no simple floor where I
don't get multiple return values). Submitted, finally got accepted (and
slightly faster than python). Further optimizations included giving the exact
ranges for certain numbers and inlining the floor function.

After an hour or two of optimization work I got it down to about 66% of the
python run time. Not even close to what I was expecting in runtime
performance, especially considering the 'SBCL is just as fast as C' arguments
that are all around.

Not that I'm not going to stop learning CL, but it seems the performance
claims just don't add up to the performance reality (for this case). And the
development time was doubled just to make the program run acceptably fast.

As Paul Graham said in ANSI Common Lisp: Lisp lets you write slow programs
fast, and fast programs slow. But in many cases 'good enough' is just that and
I can really see how python excells in this regard and how it's taken over the
hearts and minds of a lot of Ex-Lispers.

~~~
mahmud
Code please.

~~~
kruhft
Here is python code that I first used to solved to problem in the time
allowed:

    
    
        #!/usr/bin/env python
    
        import sys
        import math
    
        count = int(sys.stdin.readline())
        for i in xrange(0, count):
            n = int(sys.stdin.readline())
            ndiv5 = math.floor(n / 5.0)
            if n >= 25:
                ndiv5 += math.floor(n / 25.0)
            if n >= 125:
    	    ndiv5 += math.floor(n / 125.0)
            if n >= 625:
        	    ndiv5 += math.floor(n / 625.0)
            if n >= 3125:
        	    ndiv5 += math.floor(n / 3125.0)
            if n >= 15625:
        	    ndiv5 += math.floor(n / 15625.0)
            if n >= 78125:
        	    ndiv5 += math.floor(n / 78125.0)
            if n >= 390625:
        	    ndiv5 += math.floor(n / 390625.0)
            if n >= 1953125:
        	    ndiv5 += math.floor(n / 1953125.0)
            if n >= 9765625:
        	    ndiv5 += math.floor(n / 9765625.0)
            if n >= 48828125:
        	    ndiv5 += math.floor(n / 48828125.0)
            if n >= 244140625:
        	    ndiv5 += math.floor(n / 244140625.0)
            print int(ndiv5)
    

And here is my optimized Common Lisp version:

    
    
        (declaim (optimize (speed 3) (space 3) (safety 0)))
        (declaim (inline floor))
        
        (defun calc-trailing-zeros (n)
          (declare (type (integer 0 1000000000) n))
          (let ((ndiv5 (floor n 5)))
            (declare (fixnum ndiv5))
            (if (>= n 25)
        	    (setq ndiv5 (+ ndiv5 (floor n 25)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 125)
        	    (setq ndiv5 (+ ndiv5 (floor n 125)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 625)
        	    (setq ndiv5 (+ ndiv5 (floor n 625)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 3125)
        	    (setq ndiv5 (+ ndiv5 (floor n 3125)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 15625)
        	    (setq ndiv5 (+ ndiv5 (floor n 15625)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 78125)
        	    (setq ndiv5 (+ ndiv5 (floor n 78125)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 390625)
        	    (setq ndiv5 (+ ndiv5 (floor n 390625)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 1953125)
        	    (setq ndiv5 (+ ndiv5 (floor n 1953125)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 9765625)
        	    (setq ndiv5 (+ ndiv5 (floor n 9765625)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 48828125)
        	    (setq ndiv5 (+ ndiv5 (floor n 48828125)))
        	    (return-from calc-trailing-zeros ndiv5))
            (if (>= n 244140625)
        	    (setq ndiv5 (+ ndiv5 (floor n 244140625)))
        	    (return-from calc-trailing-zeros ndiv5))))
        
        (let ((count (parse-integer (read-line))))
          (declare (fixnum count))
          (dotimes (n count)
            (declare (fixnum n))
            (let ((factn (parse-integer (read-line))))
              (princ (calc-trailing-zeros factn)) (terpri))))
    

Notice the Python code doesn't even have the early returns that the Lisp code
does. The Python code comes in at 5.42 seconds; the optimized Lisp version's
best time was 3.39 seconds. I know the algorithm to solve the problem is
probably not the most elegant, but it does get accepted. Any ideas on how to
optimize the Lisp code further would be appreciated.

~~~
ced
Hey, I was curious about your claims, so I ran both versions on my computer,
and SBCL came out 10X faster. For one million calls (count=1000000) and n
fixed to 100000, SBCL took 0.6 seconds versus 8.6 seconds.

One thing I did, though, was to call both functions directly with arguments,
and not rely on read-line/readline. That might be the difference, I wouldn't
be surprised if Python was optimized for text processing, and SBCL was lazier
about it (Lisp programs call read et al. infrequently). Your code is decently
optimized, IMO. Cheers.

~~~
kruhft
Thanks for checking. SPOJ uses SBCL 1.0.18 so that might be a bit of an issue,
since it seems to be a couple of years old. I was thinking that the input
routines might have been a bit of a problem and that CL isn't optmized as much
for that type of processing. Maybe something to look into in SBCL code base
for improvement.

------
jrockway
Someday when I fix my blog software, I am going to write the following blog
post:

"How should I determine whether or not to use Language X?"

1) Do you want to use Language X? If you don't want to use it, don't.

2) Do you communicate with people that use Language X? Programming doesn't
happen in a vacuum. You probably don't want to read the language
implementation source code to determine how to call a function. So it's good
if someone is around to teach you the language or to write docs for you. It's
also nice to have libraries, because when you want to write Awesome Web 2.0
App, you probably don't want to write a sockets library too.

If you answered yes to both questions, you should use Language X. If you start
using it and don't like it, then use something else. Please do not write a
blog post about your experience, because nobody cares.

------
parfe
[http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=s...](http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=31402)

I couldn't find a date on the article, but it seems it's only web example is
no longer valid.

~~~
vixen99
"its only web example". It's means and can only ever ever mean "it is".

~~~
adambyrtek
Technically you are right, but your comment doesn't add anything to the
discussion. Typos happen, and I wouldn't be so anal about that. There are more
constructive ways to get upvotes.

~~~
dkarl
He improved every future discussion in which parfe participates.

~~~
parfe
Not really. It was a typo. I hope you aren't so distracted by a spurious
apostrophe that it would detract from a discussion.

------
levicampbell
I had honestly considered writing my website in common lisp, but discarded
that idea because I couldn't find good documentation for the RESTAS web
framework.

~~~
sedachv
Do you mean the official documentation, or 3rd party examples and tutorials?
Andrey has been working hard at translating the official docs to English the
past few months: <http://restas.lisper.ru/en/>

As for tutorials, you are right that there could be more. Between
<https://github.com/archimag/rulisp> and <https://github.com/archimag/cliki2>
there are some good example sites built in RESTAS.

------
warmfuzzykitten
[advertising]

~~~
tomjen3
Actually PR, but yes.

Just like everytime you hear the words "Zed Shaw", "Linus", "RMS", "Ruby on
Rails", "Node.js".

It is all branding.

