Type systems: This is the biggest issue in my opinion. Most Lisps don't really have any formal notion of a type system. Common Lisp kind of does; it's pretty baroque, but if you look deep enough, you'll see it's way behind the systems offered by ML derivatives, Scala, or Haskell. Such a thing would be incredibly hard to bolt-on. Shen sort of offers a richer system in very weird syntax, but the compiler just throws that info away and doesn't make it useful. Typed Racket is another approach.
Polymorphism: In Common Lisp, I can't really make efficient, generic data structures. In Haskell, I can, by making the data structure polymorphic. Haskell will know the types at compile time and can optimize accordingly. In CL, I must do ugly things like provide equality predicates to functions, as opposed to having them associated to the data structure itself. François René Rideau has been trying to patch this up by something called the "Lisp Interface Library".
Functional optimizations: In any Lisp, you typically need a special library for doing optimization of functional code. Deforestation and so on can only be done with special packages like reducers in Clojure or SERIES in Common Lisp. Again, they aren't broad enough to cover the language as a whole.
Immutable/persistent data structures: Clojure has this pretty covered. It is possible to implement these data structures in other Lisps, like Common Lisp, but they're not bound to be very efficient.
OS integration: Not much of a comment. For Common Lisp at least, the language was designed without POSIX or Windows in mind. So it has really weird pathname conventions, poor ways of targeting the user environment, a weird idea about files, etc.
Code organization and packaging at the language level: This is an issue with CL and Scheme. Lisp doesn't really have the concept of an explicit API, or modules of code. There's no concept of a compiled shared library. Code is almost always distributed and integrated by source.
...
The list goes on. You can implement lazy data structures in Lisp, but it's hard to really integrate them in the language. Lazy data structures provide tons of benefits, especially by moving the boundaries for abstraction, but there seems little hope to make this a part of Lisp.
A big problem is that even if some of the above concepts are implemented in various languages (and as I stated, some of them have), they're usually implemented as a part of a toy language (even if it's not intended to be a toy), and are never really integrated well with what exists. Because of this, I don't think it's fair to say Lisp has all of these features, even if there exists dialects of Lisp that implement some of them.
> In CL, I must do ugly things like provide equality predicates to functions, as opposed to having them associated to the data structure itself.
> Immutable/persistent data structures: Clojure has this pretty covered. It is possible to implement these data structures in other Lisps, like Common Lisp, but they're not bound to be very efficient.
You really should take a look at FSet[0]. Not only does it provide fairly efficient persistent implementations of functional datatypes -- not as fast as Clojure's, perhaps, but not bad -- but it allows you to associate your equality predicates with your datatypes rather than passing them to every operation explicitly. (In fact, FSet currently provides no way to pass the predicate explicitly. Some people, including Faré, think this is an unfortunate omission, but I've never needed to do that.)
I know about FSet and have used it in production. It indeed is a library that has an immutable data structure.
FSet's solution to the equality "issue" is by having a generic function COMPARE which will return :LESS, :GREATER, and whatnot.
FSet goes to length describing the issues embedding immutable data structures in an inherently mutable language. Things like RENAME-PACKAGE screw up invariants that FSet expects.
Lastly, FSet admits that it isn't exactly performant, it's just good enough, which was the point I was trying to make.
Aside from a few gripes I have, it's a good library to use, especially in multithreaded environments where you don't want to deal with locking and whatnot.
Glad to hear you like FSet! (Not sure if you noticed: I am the author.)
I protest, though, that there's nothing about Common Lisp that makes FSet slower than Clojure. Rich Hickey used a very clever data structure called a Hash Array-Mapped Trie to implement Clojure sets and maps, and (I think) an Okasaki-style sequence implementation. FSet, in contrast, uses balanced binary trees for all these types. That's the source of the performance difference, not anything about CL.
> Shen sort of offers a richer system in very weird syntax, but the compiler just throws that info away and doesn't make it useful.
While I share your belief in the importance of type systems, I don't understand this remark.
I haven't used Shen (or Qi), but it's at the top of my list of interesting languages to try. As I understand, the optional type system is a core Shen feature. The syntax may be unlike other programming languages, but is taken directly from type theory. Can you go into more detail, perhaps contrasting with Haskell?
Thanks. I don't partake in any newsletters and don't really write about languages in general, though I am interested in them. As I said in my parent post, there are ramblings on programming/Lisp/etc on [1]. There are topics related to the above that I plan on writing about, including the somewhat messy state of type/data-driven programming in Lisp, and so on.
Agreed with the polymophism efficiency concern. I was doing some farting around with heaps-the-data-structure earlier this year and changing my DEFUN to/from DEFMETHOD made a decent difference.
`(defmethod insert ((heap heap)) ... )` is distinctly slower than `(defun insert-heap (heap) ... )` (even after as much tuning of SBCL as I could).
Polymorphism: In Common Lisp, I can't really make efficient, generic data structures. In Haskell, I can, by making the data structure polymorphic. Haskell will know the types at compile time and can optimize accordingly. In CL, I must do ugly things like provide equality predicates to functions, as opposed to having them associated to the data structure itself. François René Rideau has been trying to patch this up by something called the "Lisp Interface Library".
Functional optimizations: In any Lisp, you typically need a special library for doing optimization of functional code. Deforestation and so on can only be done with special packages like reducers in Clojure or SERIES in Common Lisp. Again, they aren't broad enough to cover the language as a whole.
Immutable/persistent data structures: Clojure has this pretty covered. It is possible to implement these data structures in other Lisps, like Common Lisp, but they're not bound to be very efficient.
OS integration: Not much of a comment. For Common Lisp at least, the language was designed without POSIX or Windows in mind. So it has really weird pathname conventions, poor ways of targeting the user environment, a weird idea about files, etc.
Code organization and packaging at the language level: This is an issue with CL and Scheme. Lisp doesn't really have the concept of an explicit API, or modules of code. There's no concept of a compiled shared library. Code is almost always distributed and integrated by source.
...
The list goes on. You can implement lazy data structures in Lisp, but it's hard to really integrate them in the language. Lazy data structures provide tons of benefits, especially by moving the boundaries for abstraction, but there seems little hope to make this a part of Lisp.
A big problem is that even if some of the above concepts are implemented in various languages (and as I stated, some of them have), they're usually implemented as a part of a toy language (even if it's not intended to be a toy), and are never really integrated well with what exists. Because of this, I don't think it's fair to say Lisp has all of these features, even if there exists dialects of Lisp that implement some of them.