34

Does Lisp still have any special feature which has NOT been adopted by other programming languages?

By Lisp, I mean all the Lisp programming languages as a whole. I've been told how amazing Lisp is and know that many languages have been inspired by Lisp. But does Lisp still have any exclusive design feature that just cannot be done in any other language?

The reason I asked the question is that recently, being an amateur programmer myself, I began to learn Clojure just for fun, and the result is that I found lots of Lisp-related posts and comments, saying but one thing: "Lisp is unique", but other modern programming languages have already adopted and stolen lots of ideas from Lisp, like conditionals, recursion, and the function as a first-class citizen. And even metaprogramming can be done by many languages.

Did I miss out something and is "Lisp still different"?

Or I'm lucky because other modern languages have stolen all the good parts from Lisp so that it's not necessary to dig into the parentheses Lisp world, and "Lisp was different".

iceX
  • 711

6 Answers6

27

A canonical reference for this type of question is Paul Graham's What Made Lisp Different. The two remaining key features of Lisp that are not widely available, according to this article at the time of its writing, are:

8. A notation for code using trees of symbols.

9. The whole language always available. There is no real distinction between read-time, compile-time, and runtime. You can compile or run code while reading, read or run code while compiling, and read or compile code at runtime.

The commentary addresses each point and names popular languages where that feature is available.

8, which (with 9) is what makes Lisp macros possible, is so far still unique to Lisp, perhaps because (a) it requires those parens, or something just as bad, and (b) if you add that final increment of power, you can no longer claim to have invented a new language, but only to have designed a new dialect of Lisp ; -)

Note that this article was last revised in 2002, and in the past 11 years there have been a wide variety of new languages, some of which may incorporate all these Lisp features into their design.

Greg Hewgill
  • 10,201
14

The question is a difficult one to answer, as someone would have to know all languages in order to know that no other has a particular feature available in Lisp, so the following is based on the languages I have experience with.

Off the top of my head, conditions are something that I haven't seen in any other language. Think 'exceptions', but where the call stack is not unwound, and where the caller can send a recovery value to the exception site , but without disturbing the call stack in between the handler and the source of the exception. To be fair, this is really just a special application of continuations, so Ruby and Scheme (at least) can do this.

Lisp's macro system benefits from regularity/homoiconicity, but Scala is planning to incorporate them as a stable feature in 2.12 and Template Haskell claims similar features. I'd argue that they'll be more syntactically complex than with Lisp, but the compile-time generation of code is there regardless.

Come to think of it, though, straight building of forms is only one kind of macro available in Lisp: I haven't seen an equivalent of compiler or reader macros anywhere else.

The ability of some dialects (e.g. SBCL) to save a complete, resumable process image is cool, but again it isn't unique: Smalltalk has been doing that for decades.

Many other languages allow destructuring assignment on when returning arrays, but the #'values and #'multiple-value-bind/let-values approach still seems to be specific to Common Lisp and Scheme (which can still do 'regular' destructuring as well). Perl's 'wantarray' allows a function to determine whether it's being called in a scalar, list or void context so it can adjust its return value in a similar(-ish) way, but I've not seen 'true' multiple return values outside of Scheme/CL.

In terms of language features, there's probably not much that Lisp can do that other languages can't (Turing completeness being what it is). What it is, however, is a language where the code is expressed in terms of its own data structures, making the Big Idea™—that code is data—something that's relatively easy to work with.

Mark Hurd
  • 343
4

After so many decades, I don't think there is anything exclusive to Lisp. But even today, there are many interesting things that are hard to find outside Lisps. A few things that come to mind:

  • A high-quality object system with sophisticated meta-protocols (i.e. CLOS) is not remotely popular.
  • multi-methods pop up from time to time somewhere, but most people never heard about them.
  • As others have pointed out, the condition system is quite sophisticated comparing to popular exception handling mechanisms.
  • A compact representation of the language's semantics (eval), an empowering approach to define one's language and making it available for straightforward deep adaptations (see SICP) -- "eval" functions of current popular languages simply don't share the same properties.

Finally, there is a lot more to learn from Lisp that is not about the language itself but became part of Lisp history and got lost in time. E.g. Interlisp, Symbolics Genera, etc...if you never put your hands on Genera, see this comp.lang.lisp thread where Kent Pitman describes how "Emacs is only a pale shadow of Genera's Zmacs" -- which was all enabled by having a powerful Lisp system which Zmacs was part of, which ran on a Lisp Machine.

Thiago Silva
  • 1,039
4

It's not necessarily a certain single feature. It's the whole look and feel, and how certain sets of features work together.

JavaScript or Java have a lot of features of Lisp (virtual machine, compiler/evaluator, garbage collection, etc.). But JavaScript for example lacks the symbolic programming part, it lacks mathematic capabilities (internally it has only floats), it lacks the error handling, and so on.

Many Common Lisp systems are optimized for a development way where one extends new software incrementally, by extending the Lisp language in various dimensions using various meta-programming techniques - without restarting the software for a long time. Thus it needs to be flexible and extensible - but at the same time it needs to be robust. Changing the language (macros are basically a way for the user to extend the compiler) without crashing the program.

Now something like JavaScript is also used to extend a program, typically a web browser. But most of the time one does not much meta-programming in JavaScript - besides some OOP hackery.

Example:

One can implement a general advanced mathematics software for the domain of computer algebra in mostly two ways: write the engine in C with a specialized language on top (like Mathematica) or in some more advanced Lisp dialect. Macsyma/Maxima in Common Lisp, Reduce in Standard Lisp, Axiom in Common Lisp.

(There are also one or more written in Python.)

There are not many systems which offer the feature set of something like Axiom, which runs on top of Common Lisp.

What made Lisp attractive for these types of applications is a mix of features: advanced basic maths (bignums, ratios, ...), symbolic computation, interactive compiler, etc. It's quite possible to get these things by implementing them in a low-level language. That way, one will have implemented 50% or more of a typical Lisp system.

Rainer Joswig
  • 2,240
  • 13
  • 17
2

Lisp has many dialects, and each of them has its own set of features. My favorite feature that is unlikely to be adopted by any other language is the "spaghetti stack" from Interlisp.

The spaghetti stack is like a closure, but on steroids. It saves not only the current function, but the entire context up to the top of the stack. Something like a co-routine, except that you could create these arbitrarily, resulting in a hierarchy of stack contexts.

ddyer
  • 4,078
2

Not as far as I am aware of. Forth is easily as dynamic as Lisp, perhaps more so since dynamic code in Forth looks like regular Forth code while Lisp macros tend to use different features than regular Lisp code (in Clojure at least I have never used syntax quote outside of a macro) and as a result they look really different from regular Lisp code. As an example of how dynamic Forth is, here is a way to implement comments in Forth:

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )
stonemetal
  • 3,381