4

I am currently trying to wrap my head around packages, systems & co.

I now have read Packages, systems, modules, libraries - WTF? a few times, and I think I'm still having difficulties to get it right.

If I simply want to split a Lisp source file into two files, where one shall "use" the other - how do I do that? Do I need to build a system for this? Should I use a module? …? I'm coming from a Node.js background, and there you can simply say

var foo = require('./foo');

to get a reference to what's exported in file foo.js. What is the closest equivalent to this in Lisp?

I understand that ASDF is for systems, and that it is bundled as part of Quicklisp, at least according to its documentation:

ASDF comes bundled with all recent releases of active Common Lisp implementations as well as with quicklisp […]

Okay, Quicklisp is for libraries, but what is their relationship? Is Quicklisp something such as a "package manager" in other languages? And if so, then what exactly does ASDF provide?

Sorry for these many questions, but I think it just shows the trouble I have to understand how to structure Lisp applications. Any help would be greatly appreciated :-)

Golo Roden
  • 140,679
  • 96
  • 298
  • 425

2 Answers2

8

System

For structuring large system use a system management tool. A 'free' one is ASDF.

You would need a system declaration, which lists the parts of you library or application. Typically it goes into an own file. Then you load a system or compile a system. There should be tutorials how to do that.

A simple Lisp system might have the following files:

  • a system file describing the system, its parts and whatever other stuff is needed (other systems)
  • a package file which describes the namespaces used
  • a basic tools file (for examples functions used by the macro)
  • a macro file which lists the macros (used so that they get compiled/loaded before the rest of the software)
  • one or more other files with functionality.

Quicklisp is independent of that. It's a software distribution tool.

Quick hack to compile and load files

But you can also compile and load files the old fashioned way without a system tool:

(defparameter *files*
  '("/yourdir/foo.lisp" "/yourdir/bar.lisp"))

(defun compile-foobar ()
  (mapc #'compile-file *files*))

(defun load-foobar ()
  (mapc #'load *files*))

(defun compile-and-load ()
  (mapc (lambda (file)
           (load (compile-file file)))
        *files*))

In reality there might be more to it, but often it's enough. It should be easy to write your own building tool. A typical system tool will provide many more features for building more complex software in a structured way. Many of the ideas for these tools reach back at least 35 years. See for example the Lisp Machine manual, here the edition from 1984, chapter Maintaining Large Systems.

The role of files

Note that in plain Common Lisp the role of files and its semantics are not very complex.

A file is not a namespace, it is not associated with a class/subclass or an object, it is not a module. You mix Lisp constructs in a file like you want. Files can be arbitrary large (for example one complex library has a version where it is delivered as single source file with 30000 lines). The only real place in the standard semantics where a file plays a role is when compiling a file. What side effects has compiling a file? What optimizations can a compiler do?

Other than that it is assumed that the development environment provides services like load and compiling groups of files aka systems, provide overviews of compilation errors, record source locations of definitions, can locate definitions and more. A tool like ASDF handles the system part.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
  • Additionally to this, reading http://www.flownet.com/gat/packages.pdf and http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html helped a lot to understand packages. Thanks :-) – Golo Roden Jun 13 '15 at 13:26
  • Rainer, why do you use quotes around 'free', regarding ASDF? – Faré Jun 17 '15 at 15:00
  • Also, not that ASDF 3.1 has support for the lighter-weight quick-build / faslpath style of system building, where there is a one to one correspondance between files and packages and systems. – Faré Jun 17 '15 at 15:02
  • Finally, what ASDF does as compared to your manual system build is allow you to decouple software development from system administration, so you don't need absolute pathnames pointing to both your own files and more problematically their dependencies, all in your build specification. ASDF will find the dependencies. – Faré Jun 17 '15 at 15:04
  • See notably my talks on Common Lisp as a Scripting Language: https://github.com/fare/asdf3-2013 – Faré Jun 17 '15 at 15:40
  • @Faré: quotes around 'free', because it is'free' in the FSF sense. There are proprietary system tools. Generally it would make sense, if you add an answer. Comments are not the best place to add these informations. – Rainer Joswig Jun 17 '15 at 16:14
2

There is a require function in Common Lisp, but it deprecated. If you simply want to split your code in one or more pieces, to use it interactively in the REPL, you can put the code in different files and then load each of them. If instead you want to write a full lisp project, I have found very useful the quickproject package, that provides a simple starting point for the creation of new packages.

Renzo
  • 26,848
  • 5
  • 49
  • 61