Skip navigation

Monthly Archives: June 2014

Python limitations:

No macros
This is inevitable in a non-Lisp language.

Anonymous functions are limited to a single expression, and no statements
This is excusable; Python’s indentation-based syntax makes it hard to express inline functions unambiguously.

One can only ‘break’ out of the innermost block
Guido van Rossum claims that named blocks are rarely needed, and thus shouldn’t be added to the language. Judging from this, the Python philosophy is to keep the language simple and easy to master; a new feature should only be added if it is frequently needed and considered proper style. In practice, this often leads to having to shoehorn one’s conception of a problem into the way Python dictates it to be expressed, especially if one has a background in a more flexible language like Lisp.

Common Lisp does have extensible syntax (macros), full-fledged anonymous functions, and named blocks.

Even writing a simple CLI Yatzy game in Python, I find myself wanting to use macros, anonymous functions and named blocks. Macros allow arbitrary blocks of code to be wrapped in error-handling code, like (handle-errors (dostuff)). Anonymous functions allow the calculation functions to be defined directly in a dictionary instead of defined as named functions and then referred to by name in the dictionary, only to discard the names. Named blocks allow breaking out of a loop from an inner loop. These limitations give me the feeling that I’m fighting against the language.

There is a reason people become zealous about Lisp; it allows one to bend the language to one’s will instead of submitting to its constraints.

So why use Python? Well, there are some reasons. While Python’s infix/indentation based syntax poses some limitations in expressiveness, Python code is often terser and clearer than the equivalent Lisp code. Here are some illustrative examples:

x=y+z
(setf x (+ y z)

x[y,z]
(aref x y z)

x[0][1]
(aref 1 (aref 0 x))

if foo:
    do1()
    do2()
else:
    do3()
    do4()

(if foo
    (progn
      (do1)
      (do2))
    (progn
      (do3)
      (do4)))

Python also has a much better selection of libraries than Lisp. A language has to be popular to be good, and the Lisp community is not just small, but very fragmented across dialects (CL, Scheme, Clojure, Dylan..) and implementations (for CL: CMUCL, CLISP, SBCL, ECL..), so there is a limited selection of tested, documented, portable libraries. (Clojure seems promising in this regard, being built on the Java platform and able to use Java libraries.)

So what is the right choice? I can only conclude that it depends on the project and one’s tastes.

Advertisements