ANSI Common Lisp (1995)
paulgraham.com
paulgraham.com
From the CL spec, to Norvig's "Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp," to both of pg's CL books (this one and 'On Lisp') -- these all feel readable, even re-readable, and entertaining.
And of course the same can be said of the Erlang books -- I'll read anything I find by Joe Armstrong or Robert Virding.
In both cases, authors are able to joyously present the language's unique superpowers and ways of thinking (CL-style macros, OTP). But I think a crucial factor is that, since both languages are very practical -- in terms of their reason-to-exist, as well as what they provide 'out of the box' -- the writing tends to be imbued with the energy and possibility of actually building things.
Two things:
1. This isn't true. Common Lisp style emphasizes looping; Scheme emphasizes recursion.
2. What's wrong with tree recursion anyway?
Norvig switched to Python when he left NASA and went to work for Google. He wasn't going to convert Google's culture to one that embraced Lisp.
that commonlisp advocates for some linear looping constructs is one thing but, to me, it's only a thin part of the top of the iceberg
2) nothing wrong to me, but I suppose that to the mainstream, if you had to pick between sexps, lambdas and treerec idioms over perl regexes or php arrays/templating, or jQuery dom shenaningans .. it probably look too dry to bear any value (culture shock)
Again, that's only my opinion :)
The idea here is that Nix should be usable for builds at the same abstraction level as Bazel (i.e. individual build targets), while retaining the power of the rest of the ecosystem.
Example build "manifest" using buildLisp.nix: https://git.tazj.in/tree/third_party/lisp/alexandria/default...
This has a few additional neat benefits, such as making it possible to easily spin up a REPL with the correct Lisp & dependencies loaded from within Emacs[2].
There's also a similar project I did for Go[3] to prove the general viability of the concept.
[0]: https://git.tazj.in/tree/nix/buildLisp/
[2]: https://git.tazj.in/tree/tools/emacs-pkgs/nix-util/nix-util....
Edit: Also, why do you need to specify all the .lisp files in the build(?) file?
For libraries, it builds an output with a concatenated FASL for all inputs (which reference the sources by their exact hash in the Nix store, which means that they will be distributed alongside).
For programs, it dumps an executable image (save-lisp-and-die with `:executable t`).
For `buildLisp.sbclWith` it creates an SBCL that loads an image pre-loaded with all the dependencies.
> Why would I use this over, say, Quicklisp?
Quicklisp is one small bit of the puzzle (the distribution of packages using ASDF).
Using Nix for the task replaces Quicklisp, ASDF, your distribution package manager used to install your Lisp, your distribution package manager used to install native dependencies of your Lisp code (e.g. cl+ssl with openssl[0]), your deployment tooling and generally your entire software packaging and distribution stack which leaves you with one homogeneous system that is easily composed across language boundaries.
> why do you need to specify all the .lisp files in the build(?) file?
I modeled this after the way Bazel rules are normally written, where specifying each source file is common. In fact, ASDF does this too.
[0]: https://git.tazj.in/tree/third_party/lisp/cl-plus-ssl.nix#n2...
I love being able to take advantage of all the wonderful Java libraries out there. Nowadays, I think you can even use Python libraries from Clojure [0].
I especially like the Appendix D: Language Reference. CL already has very good and comprehensive reference: the Hyperspec, but the Reference in the book is good companion to to it, very much like cheat sheet. You can quickly look up things. (my copy is already braking down from the end)
And this is a project that uses that to make quickapp itself a binary you can install: https://github.com/triclops200/quickapp-cli
Both of these projects need a little TLC as I haven't touched them in a while, but they should still work.
https://www.youtube.com/watch?v=a5p8DPbaokE
Learning Lisp, Scheme or Clojure is more about learning ideas than anything else.
Later you might want to learn Alonzo Church's Lambda calculus after learning some set theory and mathematical logic.
do a toy project
read a lot of old Common Lisp code floating around on tarballs
then read Paul Graham's books
https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/...
and some of the software here:
https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/areas...
But some of that has newer versions in the usual repositories.
Have fun
Racket comes with an editor and a ton of libraries, so I'd recommend checking that out first (and then coming back to CL later maybe)
In Java/Python (and now Go), there's generally only one way to do any given thing. A business can hire people who were trained the same way to stamp out idiomatic code. Lisp hackers create works of art that no one else can figure out after they leave.
If you're working on something on your own, or with a small group of people, then you don't have to dumb yourself down. You can always rewrite it later in Java/Python/Go if the project gets big enough that replaceable cogs need to be hired.
It's possible, but it's not necessarily so. There are many Lisp code bases which are 20, 30, 40 or even 50 years old and still maintained, passing on the work to new generations of programmers.
Maxima has bits from the end 60s. Cyc is under continuous development from the early 80s onwards. SBCL is based on Spice Lisp code developed at CMU from 1981. The commercial implementations Allegro CL and LispWorks with their IDEs and libraries are under development since mid/end 80s. Axiom/Fricas computer algebra systems started the code base in the 70s at IBM as Scratchpad 2. The first MIT LOOP macro implementation was written in the 70s and then modified as Lisp dialects changed. The G2 process control system by Gensym started mid/end 80s and is still being sold. The SPIKE telescope scheduling system from NASA is still in use for various large earth and space telescopes - originally development started in the end 80s.
I've seen code bases which I could not understand from looking at them - rare, though. The biggest problems were code bases which were tied to a particular implementation and OS. For example the Sk8 multimedia development environment written by Apple is non-portable, since the Lisp code uses Mac native graphics/multimedia libraries everywhere directly from Lisp and is not abstracted in a layer.
I hope someday to work on something even remotely as challenging and worthy of applying one's brain power to as these honest projects are. In the meantime, I have to bear the "full stack developer" mania and its zombie friends.
The language had another chance in the nineties, when it became important to save not just execution time, but the programmer's time also. This is when interpreted languages like Perl and Python started showing up in a big way. I'm less confident why Lisp lost out that time, but its weird syntax is probably at least part of the reason.
As an imperative language for novices, Python (based on GvR's earlier ABC) was slow but more approachable than Lisp, and the industry had a huge influx of novices at the time (arguably still does). Now that GC and closures are table stakes, Lisp no longer has major advantages until you're ready to create DSLs.
This may no longer be true, but it's a large barrier against being adopted in many industries. That and it's kind of hard to do modern graphics with many implementations.... although they can do html serving pretty well.
LISP environments may be the start of GUI, but that code is largely locked up, or in systems that can no longer be used (I think?) Anyway, all stuff worth putting some attention on!
(note : just a lisp fan, and only an edge one, so likely no longer accurate on many points Most of the above came from reading 50s through 90s texts, and trying lisp environments at the time)
- OOP is trending downward, and for good reasons, look at Java and C#, too verbose, too top-down.
- dynamic languages are not efficient enough, especially in the cloud where they require 10 VM to do the work that could be done on a single machine with lower level languages.
- c/c++ are too low-level, hard to master/difficult to maintain.
- Rust is a mess, too verbose, too complex.
- In the FP universe, which is trending up, Haskell is too complex, F# is good but the libraries (.NET) are OOP mainly so the integration sucks. Clojure, not sure, didn't play with it but my guess is it suffers the same problem than F#.
So, personally, and not trying to convince anyone here, lisp, and especially Common Lisp with its large number of available libraries and its good development environments (emacs/slime), is getting more interesting every day.
- To code effectively one has to learn how to edit at the sexp level rather than at the word level.
- The only free editors that provide proper debugging and repl support are the ones that offer a plugin for Swank. Amongst these the best two are Emacs and Vi(m) with Emacs that has an advantage in terms of additional support for CL.
- Installing and configuring properly all the above requires some work.
- There have been recently attempts to mitigate this (e.g. Portacle) but in any case one has to learn Emacs (or Vim), Swank commands and a Lisp supporting mode such as lispy,paredit,parinfer, etc.
- Windows is a second rate citizen: there is no free Windows implementation that allows to step native code. Emacs is a second rate citizen on Windows as well. (This is mitigated by the fact that SBCL runs on Windows Subsystem for Linux).
- The commercial implementations are very good but expensive.
Now compare all of this with the typical developer that just downloads Visual Studio code and starts to write Javascript on Linux, Windows or Mac. All of the points above are of course not insurmountable but require some investment in time. One has to take a couple of weeks to start to become proficient in all above. The typical young developer doesn't have this patience.
This is exactly why CL is more common amongst who uses Emacs already: if you master Emacs the jump to CL is almost consequential.