Jump to content

# Common Lisp

From ArchWiki

Common Lisp is a highly dynamic, multi-paradigm language that emphasizes interactivity and performance. Being fully standardized, there are multiple independent implementations from which to choose.

## Installation

sbcl (http://www.sbcl.org/) is the most popular FOSS implementation and generally has the highest compatibility across the ecosystem. Its compiler produces native machine code and the project has monthly releases.

It is configured in Lisp within `~/.sbclrc`, but you may not need this depending on the dependency management strategy you choose.

### Alternate Implementations

There are numerous other implementations available. Apart from the options below, there are two major commercial Lisp implementations, Allegro and LispWorks, but they have strict licensing terms are not packaged within the Arch Linux ecosystem.

#### Active

These function seamlessly with modern tooling and can be used for serious projects.

- ABCL — Armed Bear Common Lisp: runs on the Java Virtual Machine.

  https://common-lisp.net/project/armedbear/ || abclAUR

- CCL — Clozure Common Lisp: based on Open Macintosh Common Lisp and is known for its fast compiling times.

  https://ccl.clozure.com/ || cclAUR

- Clasp — Clasp: a newer Common Lisp implementation that interoperates with C++ libraries and uses LLVM for compilation to native code.

  https://clasp-developers.github.io/ || clasp-clAUR

- ECL — Embeddable Common Lisp: compiles to C code, thus offering good C integration and embeddability.

  https://common-lisp.net/project/ecl/ || ecl

#### Historical

While packages are available for these, library and tooling compatibility is sometimes dubious, and some implementations are no longer actively maintained.

- CLISP — ANSI Common Lisp interpreter, compiler and debugger: offers good C integration and embeddability.

  https://www.gnu.org/software/clisp/ || clisp

- CMUCL — CMU Common Lisp: a POSIX-only implementation originally developed at Carnegie Mellon.

  https://gitlab.common-lisp.net/cmucl/cmucl/-/wikis/home || cmucl

- GCL — GNU Common Lisp: A descendant of Kyoto Common Lisp from the 80s and a sibling to ECL.

  https://www.gnu.org/software/gcl/ || gclAUR

- MKCL — Mankai Common Lisp: A similar descendant of Kyoto Common Lisp.

  https://mkcl.common-lisp.dev/ || mkcl-gitAUR

## Dependency Management

Dependency management in Common Lisp has traditionally involved Quicklisp, but in recent years modern alternatives have emerged.

### Vend

Vend is a simple tool for downloading and accessing dependencies directly within your project repository. It requires no special configuration.

After installing the vendAUR package, you can run `vend get` from the top directory of your project:

    [vend] Downloading dependencies.
    [vend] Fetching FN-MACRO
    [vend] Fetching ARROW-MACROS
    [vend] Fetching TRANSDUCERS
    ...
    [vend] Done.

After which `vend repl` will start a REPL session.

#### Editor Integration

##### Emacs

For Emacs users of Sly/Slime, the in-editor REPL can be configured via:

    (setq sly-default-lisp 'sbcl
          sly-lisp-implementations '((sbcl ("vend" "repl" "sbcl")  :coding-system utf-8-unix)
                                     (ecl  ("vend" "repl" "ecl")   :coding-system utf-8-unix)))

You're free to add other compilers in a similar manner. Adjust as necessary for Slime.

##### Lem

Users of Lem can open a REPL with:

    C-u M-x slime <RET> vend repl

##### Vim

Unlike Emacs which supports multiple running Lisps, Slimv requires one standalone server that persists through Vim restarts.

If we want our dependencies in `vendored/` to be visible to Slimv, we must start its server manually from our project directory:

    > cd project/
    > vend repl ecl --load /home/YOU/.vim/pack/common-lisp/start/slimv/slime/start-swank.lisp

Now, `,c` (REPL Connect) within Vim will automatically find the running server, and you can load any system available in your project and in `vendored/`.

If you want to switch projects, you would need to quit the REPL server manually and restart it as above. You may also wish to set a shell alias or create a wrapper script for the long invocation shown above.

### OCICL

OCICL is a modern alternative to Quicklisp that distributes packages as OCI-compliant artifacts from centralised package repositories. Similar to Quicklisp, it must be configured by the user to take over and manage dependency loading.

After installing ociclAUR, run `ocicl setup`, which adds the following to your compiler configuration files:

    #-ocicl
    (when (probe-file #P"/home/green/.local/share/ocicl/ocicl-runtime.lisp")
      (load #P"/home/green/.local/share/ocicl/ocicl-runtime.lisp"))
    (asdf:initialize-source-registry
      (list :source-registry (list :directory (uiop:getcwd)) :inherit-configuration))

Now, within a REPL, any attempt to run `(asdf:load-system :foo)` on an unknown dependency will automatically download it. Further project configuration is done with a `systems.csv` file, which you're intended to commit to your project repository. See the README for more setup and usage details.

### Quicklisp

Quicklisp is the original method for fetching and loading libraries into a Common Lisp program. By default it has a single, global package cache shared by all programs on your machine, and it pulls packages from a conservatively updated repository also called (perhaps confusingly) Quicklisp.

After installing the quicklisp package, it can be registered for a particular compiler as follows:

    > sbcl --load /usr/share/quicklisp/quicklisp.lisp
    * (quicklisp-quickstart:install)
    * (ql:add-to-init-file)

After which `(ql:quickload "foo")` can be used in all future REPL sessions to load a dependency, downloading it if necessary.

To update all packages installed through Quicklisp, run the following in a REPL:

    (ql:update-all-dists)

Note Generally speaking, Quicklisp assumes that all Common Lisp projects you create are located under `~/common-lisp/`. This is not true for other methods like Vend and OCICL.

#### Ultralisp

Ultralisp is an alternate Quicklisp repository that offers rolling releases of all packages, generally up-to-date with what is available on Github, etc.

To register it, run the following in a REPL:

    (ql-dist:install-dist "http://dist.ultralisp.org/" :prompt nil)

Then, if a package you load via `ql:quickload` is newer in Ultralisp, it will be loaded from there instead of Quicklisp.

### Qlot

Alternatively, if you're fine with Quicklisp but want project-local dependencies, you can use Qlot (qlotAUR).

Once installed, a project repository can be initialized to use it via:

    qlot init

#### Custom Dependencies

With Qlot, all custom dependency locations are declared within a `qlfile`. For instance, to declare Ultralisp usage, simply add:

    dist http://dist.ultralisp.org

Or to specify a dependency on your local filesystem:

    local foobar /home/you/code/common-lisp/foobar

See Qlot's README for more options.

To install declared dependencies, run:

    qlot install

#### Invoking a REPL

To load a REPL with the current Qlot environment, run:

    qlot exec sbcl

For Emacs users of Sly/Slime, consider configuring how your in-editor REPL is launched via:

    (setq sly-default-lisp 'qlot-sbcl
          sly-lisp-implementations '((qlot-sbcl ("qlot" "exec" "sbcl") :coding-system utf-8-unix)))

Adjust as necessary for Slime.

### Guix

Guix can be also used to download Common Lisp tools and libraries.

## Development Environments

### Emacs

Common Lisp development is often done in Emacs, through slime or the newer sly. Both are widely adopted in the community and have a similar usage interface.

#### Portacle

Portacle is an Emacs-based, all-in-one environment for Common Lisp development. Its aim is to easily on-ramp beginners to Lisp.

### Lem

Lem (lem-editor-gitAUR) is a newer editor in the style of Emacs, but written and configured entirely in Common Lisp. It has terminal and GUI frontends, and supports many languages.

### Vim

Slimv is a port of Slime from Emacs that utilizes Slime’s Swank backend server for a very similar experience to Emacs. To install the plugin manually:

    mkdir -p ~/.vim/pack/common-lisp/start
    cd ~/.vim/pack/common-lisp/start
    git clone --depth 1 https://github.com/kovisoft/slimv.git

Restart Vim and open a Common Lisp file. Slimv should be active, and `,c` will start a REPL server and connect you to it.

### VSCode

Support for Common Lisp in VSCode is weakest among the editors, but still possible. The Alive plugin serves as a complete development environment alongside its own LSP, which requires manual installation.

## Tips

### Managing Init Files

Library authors often test their code with multiple compiler implementations. However, each implementation has their own uniquely named init file, such as `.sbclrc` or `.eclrc`, but the content of these files is often identical. Rather than handwrite these files for each compiler, you can create one master file and symlink the others to it. For instance, if you consider `.sbclrc` to be your "master config", then:

    ln -s /home/you/.sbclrc .eclrc
    ln -s /home/you/.sbclrc .abclrc

And so on. The main init files are:

    ~/.sbclrc          # for SBCL
    ~/.abclrc          # for ABCL
    ~/.ccl-init.lisp   # for CCL
    ~/.clasprc         # for CLASP
    ~/.eclrc           # for ECL
    ~/.clisprc.lisp    # for CLISP
    ~/.cmucl-init.lisp # for CMUCL
    ~/.mkclrc          # for MKCL
    ~/.clinit.cl       # for Allegro

### Less Verbose Compilation Output

SBCL in particular can be quite enthusiastic about the number of compiler "notes" it outputs. To silence these notes, while still displaying the usual errors and warnings, set the following in your `~/.sbclrc`:

    (declaim (sb-ext:muffle-conditions sb-ext:compiler-note))

## Troubleshooting

### Quicklisp can't load a local project

`(ql:quickload "...")` is used to load both external dependencies but also local projects. However, if your local project is not located under `~/common-lisp/`, it will fail to load (or may even be pulled from online if you've published it).

In truth, Quicklisp is just fetching and organizing packages. Internally, it uses the ASDF build system to actually load them. It's also possible to load any local project or a package you've already downloaded via `(asdf:load-system "foo")`, and by default ASDF only looks in `~/common-lisp/` for local projects.

While configurable, a simpler way around this is to use a symlink:

    ln -s /home/you/code/common-lisp/ common-lisp

Note If using Vend, OCICL, or Qlot, the above symlink isn't necessary. As long as you have set them up correctly, `(asdf:load-package "foo")` will "just work".

### What are Projects, Systems, and Packages?

The rest of this article has used the term "package" in the way it is usually used in other programming languages, synonymous with "library". However, although standardized in the mid-90s, the earliest forms of Common Lisp date from the 80s, and so terms involving project management differ. In essence:

- Project: A group of systems. Sometimes called a "workspace" in other languages.
- System: A group of packages. These can represent both libraries and "executables".
- Package: A group of functions and type definitions. Often called a "module" in other languages, but can span multiple files.

As you can see, what is usually called a library elsewhere is known as a "system" in Common Lisp. Hence the name `asdf:load-system`. See here for an example of an inter-depending, multi-system project.

## See also

- Common Lisp Docs Modernized online documentation.
- The Community Spec: More online stdlib documentation.
- The Common Lisp Cookbook: HOWTOs for many topics.
- Awesome CL: An overview of the ecosystem.
- Quickdocs: Quicklisp library lookup.
- Portability: Compiler implementation compatibility listing.
- Wikipedia:Common Lisp
- Cliki: The Common Lisp Wiki

Categories:

- Lisp dialects
- Lists of software

Common Lisp
Add topic