Why is Python popular, while Lisp and Scheme aren't?

Alexander Schmolck a.schmolck at gmx.net
Sun Nov 24 19:46:22 EST 2002


Martti Halminen <martti.halminen at kolumbus.fi> writes:

> - LOOP isn't the only iteration construct: I use usually DOTIMES, DOLIST
> or the mapping functions for simple cases. The old DO also exists for
> oldtimers.

Sure, loop isn't the only iteration construct, but that doesn't really make it
any better, does it? Especially given that all suffer from the fact that they
only work on a quite small number of containers.

> Except that those are rather new languages in comparision, from a time
> the machine performance had already risen to acceptable values. For
> comparision, at the time Lisp Machines were the fastest workstations on
> the planet, they had clock frequencies like 4 MHz. The competition ran
> 16 MHz Motorola 68020:s.
> (Cray 1 had 80 MHz, IIRC.)

This seems a curious argument to me: Ansi CL is about 1994, so it is actually
newer than python and perl. The fact that things called "lisp" had been around
before than should only have made it easier (bigger potential user base,
greater maturity, efficient compilers etc.) for CL to compete against those
newcomers.

> 
> No such thing as "iteration class" in the language: Lisp had already
> existed for a quarter century before it got a standardized object system
> (plenty of non-standard, non-compatible versions before that), so the
> control flow constructs are rather othogonal to the object system.

Sure, but a reason is not an excuse (there are also plenty of reasons why C++
OO leaves much to be desired :)

> 
>  
> > Now if you want to define you own collection classes, you're really in for a
> > hard time:
> 
> I fail to see what is so hard in that. Obviously you have to design your
> own wrapper class if you want similar behaviour from different data
> structures, given that the language doesn't have it built-in, but as you
> yourself show, any given operation is only a few lines.

But that is besides the point. The python ``x = cont[indx]`` will likely
continue to work even if I choose to replace ``cont`` with some other
container type later. Same for ``for i in cont: ...`` etc. This is a fairly
important abstraction barrier.


OTOH ``(let ((x (gethash key hash)) won't. T Sure, I could go along and define
my own generic accesor functions (CL is powerful enough for that) just like
everyone defines their own module and OO system in scheme (scheme is powerful
enough for that).


>                                      ;; *why* this arg-order?
>                Why not? It is consistent with most of the language, [...]
> ELT probably for similarity with AREF.

Well, if you prefer then elt is inconsistent :)





>               - For printing the usual idiom is usually just (print
> container), though hash tables do not have a defined machine-readable
> output form. Nothing to prevent you from defining one.

The print statement was just to have some body for the loop. The equivalent
idiom in python is repr(container) (potentially eval'able) or str(container)
(more human readable).

> For that matter, it is a macro, and sources are available, so expanding
> it to handle anything else you wish is possible, with no runtime
> performance implications. Not that many wish: it is quite sufficiently

Well maybe in theory, but not in practice. The LOOP macro is 

A) vendor specific, if I'm not mistaken. Although you could certainly get your
   hands on a portable LOOP implementation, doing so might not be without risk
   (for one the semantics might be subtly different, esp. given that LOOP is
   often thought to be underspecified)

B) a little complex (a mere 37k for the CMU implementation), so that fiddling
   with it is hardly for the faint of heart.

> complex already for most people.

Well yes, but not sufficiently general. The for loop in python is not complex,
but more general in that it takes an infinite variety of container classes
(including lazy ones, which obviously adds expressiveness). And I should
suspect that people would actually like to extend loop if it weren't such a
nightmare (also note that e.g. emacs's (cl) LOOP *is* extended).

> 
> > Similarly, functions like
> > concatenate only know about lists and arrays (which all can't even be
> > subclassed, right?).
> - Strings too, as a subclass of arrays. As that was about all
> system-defined types with sensible semantics for concatenation, I don't
> know what you are missing. I've never had any reason to wish subclass
> built-in types, so I don't see it as a problem.

Well, the python developers also thought that not being able to subclass
builtin types wouldn't be a problem. When they realized that the difference
between (builtin) types and classes was actually quite a problem they had to
put in quite some effort to redeem the situation. Admittedly, the situation is
a bit different for python (e.g. because you can write methods for classes you
don't "own" in CL). But why shouldn't one want to have e.g. a hash-table that
always returns a default key instead of nil, just as a trivial example?

 
> To some extent this is a style difference in language usage: you seem to
> want something like C++ -style overloading, making your own
> constructions to hide in built-in behaviours. Most CL programmers are
> happy to leave the language built-in parts alone (unless explicitly
> defining a new language for some reason), and defining their own stuff
> with different names, thereby reducing surprises for readers. In reading
> somebody's C++ code I can never guess what + does this week, reading CL
> I can be relatively safe assuming (+ a b) sums numbers, (plus a b) is
> probably my own matrix multiplication stuff in my code [unless it
> happened to be old Maclisp stuff...].

I think you are conflating conflation and abstraction here :)

Overloading `+` to perform concatenation as well as addition is IMHO a really
stupid idea, because they have entirely different semantics (and you can even
end up with cases where you'd really like to have both concatenation and
addition on the same type: e.g. numerical arrays).

Unified item access, setting and deletion OTOH is an abstraction and thus
helps to produce better code. If you disagree, try replacing all instances of
SETF in your code with SETQ. Or better yet, all instances of (+ float float)
with (+. float float), a la ocaml :)

> 
> Now what tools did Python have to define your own control flow
> constructs ? :-)

Well, for some cases where lispers think you'd need macros the iteration
protocol and generators are actually enough (and, I guess, also better). Of
course there are quite a few things you can conveniently do with macros that
are awkward in python and CL has many cool things python hasn't -- but I
really think iteration and containers are better done in python.

alex



More information about the Python-list mailing list