19 ms·
It is a very multi-dimensional issue. While all these languages belong to the same family, they also take some time to learn, and each has its specific strength
by jnxx 6y ago
It is a very multi-dimensional issue. While all these languages belong to the same family, they also take some time to learn, and each has its specific strengths. It is probably very helpful to think about what matters most to you, and pick what matches your needs best for the first language.
Here some axes of distinction:
1. supported programming styles
2. support for concurrency
3. performance of generated code and parallelism
4. floating-point performance
5. level of standardization
6. closeness to the system and capability to call into C functions, or functions with C ABI
7. suitability for scripting and stand-alone programs
8. GUI programming
9. Comprehensiveness and beginner-friendliness of documentation
10. REPL Programming
11. Libraries
12. Licenses
Here what I know about the languages you name:
(I also mention ABCL = Armed Bear Common Lisp a few times, just to illustrate that you also can run Common Lisp on the Java Platform).
1. supported paradigms - Clojure is very opiniated in supporting and demanding a purely functional style. It uses purely functional data structures. Racket and Scheme support a functional style well, but allow for seamless imperative code. Common Lisp is agnostic, one can program in a purely functional way and there are libraries with purely functional data structures, but it requires much more discipline.
2. Clojure has best support for concurrency and server-like tasks, it is made for that. Racket also supports green threads, apart from its places parallelism.
3. Racket, Chez, Common Lisp and so on support OS level threads and parallelism. Chez and Common Lisp stand out as they generate the most performant code - when it comes to raw computing power, single-threaded SBCL code will be faster than multi-threaded Clojure code. SBCL, for example, also allows to add compiler hints which generate unsafe code with better optimizations (for example, indicating that integer values will only be in a specific range).
4. SBCL has by far the best floating-point performance, I think Chez comes after that, and I'd expect Racket to improve further here. Racket has also been reviewed very favourably for scientific applications (https://khinsen.wordpress.com/2014/05/10/exploring-racket/ https://khinsen.wordpress.com/2014/05/10/exploring-racket/ - Konrad Hinsen, the author, was an early contributor to Numerical Python).
5. Of all these, Common Lisp is standardized most. Especially Racket and Clojure are defined by their implementation.
6. Clojure and ABCL allow to call into Java. In turn, all of Common Lisp, Guile, Racket, Chez allow to call easily into C. There is a performance difference, I think, between most Schemes and SBCL: Calling into a C function has some extra cost because the stack is handled differently (I think it is because of continuations). I also tried to call into Rust functions from Racket and that works very nicely.
7. Clojure's startup time is simply too slow for scripting. It is also a bit hampered in that it runs on the JVM. There is babashka, which is interesting but has no mature status. Conversely, Common Lisp and Racket are well suited to scripting. It is also possible to compile SBCL and Racket programs into a single executable. I think SBCL supports this case best, for running Racket programs, an extra runtime library or a standard Racket installation is needed. Guile is also well-suited to scripting and is closer to the OS than some other Lisps.
8. Racket has a very nice support for GUI programming with a platform-independent functional API. Clojure and ABCL also allow to call into Swing and Fx code written in Java. I have not tried the rest but it looks relatively painful and brittle in comparison.
9. Racket has very comprehensive and high-quality documentation good for beginners. Clojure is also comprehensively documented, but might assume a bit more experience. Common Lisp is, as an open system, more eclectic, and this might lead especially beginners to underestimate how mature and good it is. It is very under-hyped compared to Clojure. But there is the Common Lisp Cookbook on the web, which is really good. I can also warmly recommend the books "Practical Common Lisp" by Peter Seibel, and "Common Lisp Recipes" by (corrected!) Edmund Weitz. If you want to have true understanding, and are about to write industry-grade robust software, they are really worth every cent.
10. REPL Programming: Lisps and Schemes such as Racket have a subtle difference which affects the style of programming. In Lisp, everything is dynamic and you can re-load and evaluate parts of the program when it is running. This makes for a great development environment. In contrast to that, Racket for example has a clear distinction between compilation time and run time, which gives certain safety and correctness guarantees, but requires that the program is re-loaded more often during development.
11. Libraries: Racket has a distinct "Batteries included" feeling which makes it nice for beginners. Clojure uses Leiningen which runs on top of Maven to automatically retrieve libraries, it works very well. Racket has a similar system. Common Lisp is more eclectic again, what is used today is quicklisp and asdf (see the Common Lisp Cookbook). There is also a reasonable support in OS Packages e.g. in Debian, and in addition GNU Guix is a very interesting solution for packaging of Lisp libraries and in polyglot projects.
12. Licenses: Clojure has a non-copyleft license (Eclipse License) which might be an obstacle if you want to publish copyleft libraries and code (not sure about the exact limits here but the problem is that in a Lisp system, there is less clear of a boundary of system or language code and your own code, so it is probably advisable to use a language with compatible license if you want to publish copyleft code). Racket is Apache 2 which is GPL compatible. Guile is, as part of the GNU system, GNU LGPL.
In summary, I think Racket is great for beginners, although you could start with all of them. Clojure is fantastic for servers and to learn about functional programming. Guile and Racket are great for scripting. Common Lisp, and especially SBCL requires a bit more learning effort at the beginning, but it is a really mature and highly performant system which gives you a lot of freedom.
- iainctduncan 6y agoThis is very good, I agree with almost everything. I would add the following: Guile and S7 are great for embedding in C programs. S7 is similar to Guile but permissively licensed. Gambit and Chicken compile down to C if you want to work that way. Gambit is very fast, Chicken is extremely well documented and beginner friendly. Clojure has by far the best books out for enterprise development and web dev if you want to build "normal" business apps and like books.
- bjoli 6y agoS7 is similar to guile 1.8, which was an interpreter written in C. Now guile has a pretty nice VM, a bytecode compiler, a JIT and is written in a lot more scheme.
- flavio81 6y ago> Clojure uses Leiningen which runs on top of Maven to automatically retrieve libraries, it works very well. In the same way, Common Lisp uses Quicklisp, which runs on top of ASDF to automatically retrieve and compile libraries. It works very well.
- jnxx 6y agoI generally agree. One difference is that Quicklisp + ASDF often needs to be set up manually which can be a little bit more complicated (it is, however, contained in Debian as a package, for example). Leiningen and Maven relay on version numbers for dependencies. My understanding is that Quicklisp in practice uses a "rolling release" model similar to Arch Linux - you get a current distribution, where all packages are at their newest version, and if needed, one can also roll back to earlier versions of the whole distribution. That this works with elegance is related to one aspect of Common Lisp culture which is very, very different from, say, Python or Go: Common Lisp puts a lot of importance on backward compatibility and stable APIs, it is possibly the most backward-compatible of all dynamic languages. Further, while Leiningen is a de facto standard which makes working with Clojure libraries essentially frictionles, Quicklist is just one modern way of multiple ways to include Common Lisp libraries. This difference is owed to the trait that Common Lisp is much more an open system (which I consider a good thing), while Clojure is more uniform and "managed".