Lisp - facts and myths ====================== tl;dr - Lisp's reputation as an elegant, austere and mathematically beautiful language is misleading at best. In reality, Lisp is a crocky but powerful old language that has carved out a home in academia and stubbornly refuses to die. It is more a Unix or Perl than a lambda calculus or a Turing machine. - Myth: Lisp's magic comes from first-class functions and lexical closures. - Fact: Common Lisp separates the function namespace from the variable namespace, so from some perspectives it does not have first-class functions. Scheme, and Python, uses the same namespace for variables and functions. In the Lisp world this is called being a "Lisp-1" as opposed to a "Lisp-2". Python uses its unified namespace to implement function decorators as higher-order functions, which permits some neat tricks such as [memoizing recursive functions after they are defined]. This technique also works straightforwardly in Scheme, but less straightforwardly in Common Lisp. So there's an example of how CL is less a functional language than Python! As for lexically scoped closures, Python has those too -- admittedly Python's scoping is a bit lax but it's possible to put together let-over-lambdas the same way you would in Lisp. They just don't look exactly like they would in Lisp. - Myth: Lisp's magic comes from macros. - Fact: Macros are fundamental to the language, but there isn't one particular macro system that has the magic. Different Lisps do macros quite differently. The first macro-like feature was fexpr, which appeared in the 1960s and has fallen out of use. Nowadays, Common Lisp has defmacro, and Scheme has syntax-rules and syntax-case. Some Lisps have a one-off macro system that no one else shares, such as Chicken Scheme's implicit renaming or Clojure's hygienic version of defmacro. So the lesson Lisp teaches about macros is "Have macros", and the rest is [a work in progress]. - Myth: Lisp's magic comes from conditions and restarts. Instead of crashing you can live patch your code and continue. - Fact: This feature is not broadly available across the Lisp family. Only Common Lisp has restarts. Emacs Lisp does not have restarts. Scheme does not have restarts. Further, it is up to your Common Lisp implementation to decide what restarts it is going to provide in the REPL. SBCL has a lot of good ones but smaller compilers like ECL do not. So this is an area where SBCL has magic but "Lisp" does not. - Myth: Lisp's magic comes from being a small, elegant, mathematically pure language. - Fact: People who make this claim usually cite McCarthy's [LISP 1.5 Programmer's Manual] that draws parallels between Lisp and lambda calculus. Or, they cite Alan Kay who called Lisp the "Maxwell's Equations of Software". It's true that a Lisp can be built from eight primitives, CAR CDR CONS EQ ATOM COND QUOTE LAMBDA, but no one does that [except for fun]. First, the resulting language would be pure-functional, as none of the primitives are capable of side-effects: real Lisps are not pure-functional. Second, the resulting language would not be [runtime-metaprogrammable]: you would need to implement a nested interpreter if you wanted macros or even fexprs. Finally, defining the core primitives doesn't specify the behavior of the interpreter that's executing them, so important behaviors like scoping and order of application [aren't defined]. Real minimal Lisps are built from Scheme's core primitives, which is still a pleasingly small list of stuff, but less small, and considerably less mathematically pure and harder to implement than the above. - Myth: Lisp's magic comes from being carefully and thoughtfully designed by smart people. - Fact: Lisp has committed many blunders. Examples: It used dynamic scope until the 1970s, by which time ALGOL and even C had lexical scope. The Common Lisp and Scheme standardization efforts have both suffered from legendary politics, schisms, and at least one standardized bug (Scheme R6RS records; see [SRFI-99] for background). In other words, Lisp evolved organically and made lots of mistakes, just like any other language. - Myth: There is no point in using Lisp. - Fact: If you need a Lisp-only feature or are planning to extend the language yourself, use Lisp. If not, use Python instead. [memoizing recursive functions after they are defined] [a work in progress] [LISP 1.5 Programmer's Manual] [except for fun] [runtime-metaprogrammable] [aren't defined] [SRFI-99]