1. 10
  1.  

  2. 15

    Always good to see more folks getting into Common Lisp!

    As far as I can tell, new Quicklisp projects have to be located inside ${HOME}/quicklisp/local-projects. I am not particularly happy with it, but it is not really important.

    If you want to put your projects elsewhere on your disk, you can put symlinks into local-projects that point to them. I even have a llp shell alias (“Link in Local Projects”) to run something like ln -s "$(pwd)" "$HOME/.quicklisp/local-projects" to make it easy to add the symlink (note that I keep quicklisp in ~/.quicklisp so it doesn’t clutter the file listing), since I do it so often.

    I had already installed clisp, and it took me quite some times to understand my mistake.

    I will always be annoyed at clisp for choosing such a confusing name.

    Quicklisp packages (systems?) are defined through asd files.

    Common Lisp’s terminology is confusing because it’s old and uses a lot of words that we use now (like “package”) to mean different things than people mean today. Things get easier once you internalize what Common Lisp means by the terms.

    A package in Common Lisp is a container for symbols. They’re a way to group related names (symbols) together so you don’t have to do the miserable prefixing of every name with mylibrary-... like you do in Emacs Lisp or C to avoid name clashes.

    Unlike other languages like Python/Clojure/etc, packages and files on the hard disk are not tied strongly together in Common Lisp. You can have several files that all work with the same package, a single file that switches back and forth between packages, or even write code that creates/mutates packages at runtime. Files and packages are orthogonal in Common Lisp, which gives you maximum flexibility to work however you want.

    A system in Common Lisp is a collection of code (mostly) and a description of how to load that code (and some metadata like author, license, version, etc). For example: my directed graph library cl-digraph contains a system called cl-digraph. That system has a description of how to load the code, and that description lives in the cl-digraph.asd file. It creates a Common Lisp package (called digraph).

    The Common Lisp language itself has no knowledge of systems. ASDF is a Common Lisp library bundled with most (all?) modern implementations that handles defining/loading systems. (The name stands for Another System Definition Facility, so as you might guess there have been several other such libraries. ASDF is the one everyone uses today.)

    Systems and packages are orthogonal in Common Lisp. Some systems (like small libraries) will define exactly one package. Some systems will define multiple packages. Rarely a system might not define any new packages, but will use or add to an existing one.

    A project in Common Lisp is not an official term defined anywhere that I know of, but is generally used to mean something like a library, a framework, an application, etc. It will usually define at least one system, because systems are where you define how to load the code, and if it didn’t define a system how would you know how to load the code? My cl-digraph library mentioned above is a project that defines three systems:

    • cl-digraph which contains the actual data structure and interface.
    • cl-digraph.test which contains the unit tests. This is a separate system because it lets users load the main code without also having to load the unit test framework if they’re not going to be running the tests.
    • cl-digraph.dot which contains code for drawing the directed graphs with Graphviz. This is a separate system because it lets users load the main code without also having to load the cl-dot system (the graphviz bindings) if they don’t care about drawing.

    If I were writing this today I’d use ASDF’s foo/bar system naming notation instead of separating the names with a dot, because there’s some nice extra support for that. I just didn’t know about it at the time, and don’t want to break backwards compatibility now.

    We saw how Common Lisp has no concept of a system — that comes from ASDF. Similarly, ASDF has no concept of the internet, or reaching out to somewhere to download things. It assumes you have somehow acquired the systems you want to load, maybe by sending a check to an address and receiving a copy of the code on floppy disk, as many of my old Lisp books offer in the back pages.

    Quicklisp is another library that works on top of ASDF to provide the “download projects from the internet automatically if necessary” functionality that people want in our modern world. So when you say (ql:quickload :cl-digraph) you’re asking Quicklisp to download cl-digraph (and any dependencies) if necessary, and then hand it off to ASDF to actually load the code of the cl-digraph system. Unlike ASDF, Quicklisp is relatively new in the Common Lisp world (it’s only about eight years old) bundled with any modern Lisp implementations (that I know of) (yet?), which is why you need to install it separately.

    So to summarize:

    • Files are files on your hard drive.
    • Packages are containers of symbols. They are orthogonal to files.
    • Systems are collections of code, plus instructions on how to load this code. They are orthogonal to packages.
    • Projects are high-level collections of… “stuff” (code, documentation, maybe some image assets, etc). They are (mostly) orthogonal to systems (seeing a trend here?).
    • Common Lisp knows about files and packages. ASDF adds systems. Quicklisp adds the internet.

    This is a pretty high-level view that glosses over a lot, but maybe it’ll clear things up and help you dive into the details later.

    1. 3

      Thanks a lot for taking the time to write this. I learnt a lot by reading it. Common Lisp is definitely interesting, and I am glad I finally started my journey to learn it :).

      1. 2

        Like sjl said, I never put my own projects in ~quicklisp/local-projects but always put a symlink in there. I think that was the intent of that directory.

    2. 1

      Do you also code in Python? I tried out common lisp for a short while and then decided that Python gave me all this power and more without some of the strangeness. I did like that Common Lisp could be compiled (and that there is a decompiler right there in the REPL) but all in all, I came away underwhelmed. I supposed I had been set up for that by the mythology round CL.

      I’m going to follow your further journey with interest to see how you like it in comparison to a modern dynamic language, like Python or Ruby.

      1. 4

        The mythology definitely has done Common Lisp (CL) no good, especially all the mindless advocacy of people on the orange website in the years past. Oftentimes I wondered if they even used CL or were just repeating what others said.

        That said, CL is still my favorite language because it makes most things so effortless. It doesn’t force one into a specific paradigm and one doesn’t have to remember all kinds of strange syntax rules (which can be a problem if you switch between different languages a lot).

        I’m curious what you meant with “strangeness” ?

        I do not feel Python or Ruby are more modern. They do have a more expansive community and libraries but what is more modern about them?

        1. 1

          I forget the details, but one thing that stuck out was that there was all this todo about how code was data, and yet when you went to call a variable as a function you had to use funcall rather than just do it “normally”. I also found it hard to read: I had to rely on indentation, and then the parens got in the way.

          I can see how CL was spectacular in the 1970s. But today we have Python, which has a REPL, introspection, monkey patching, good debuggers and many, many libraries often high quality ones that people have “standardized” upon. I do miss some form of compilation, which is what, to me, was a good thing about CL, as well as the gradual typing you could do (I think).

        2. 2

          The key differentiator for LISP/Scheme was that one can easily customize the language to make their problem easier to express. You break your problem downward into simpler sub-problems while using macros to bring the language upward toward easily expressing your solution. The ability to change how things work can save lines of code, make portability easier, make optimizations easier and so on. The language itself being so malleable means you don’t have to use external tooling like another language or redo your compiler/interpreter to achieve those gains.

          Python has quite a bit of power. It’s been a while since I used it. Can it currently define or redefine language features on a per-program basis using code not that different from regular Python?

          1. 1

            Hi!

            Yes, so I bailed before I learned macros. Probably makes my opinions on CL invalid.

            I saw one or two examples of macros (DSLs). They were mind blowing, but also disturbing. The danger I saw was that I could make my code unreadable by other people, including my future self because of the freedom afforded.

            @aerique says “one doesn’t have to remember all kinds of strange syntax rules” but with macros now every one and their grandfather have their own syntax rules.

            I have some confidence going into a Python code base that I will understand the intent of the coder by following the code as it is written down.

            With CL macros I felt that I would be having to go much deeper into the writers mind to understand the code.

            As it is, I have issues with the amount of malleability I get from Python.

            1. 3

              Good guess. That is a problem if macro use is undisciplined. What I recommend is using regular, boring primitives for most of the code with macros only where justified. From there, macros are much like libraries where you usually just need to know how to use them rather than their internals.

              If you ever want to try it, How to Design Programs with Racket Scheme is widely recommended to learn both Scheme and their programming approach. It’s free online.