Search code examples
common-lispslime

Auto-load dependent files in REPL


I'm fairly new to Common Lisp, coming from Clojure, and am used to something like this:

(ns x.core
  (:require [x.util :as u]))

when I start a REPL and evaluate that file, x.util is automatically compiled and available to me in x.core.

In Common Lisp I'm trying to do something similar. In main.lisp:

(defpackage x.main
  (:use :x.util))

(in-package :x.main)

(comment
 (load "util.lisp"))

and in util.lisp:

(defpackage x.util
  (:use :common-lisp)
  (:export :foo))

(in-package :cl-blog.util)

(defun foo () 3)

the only way I know to have access to foo from util in main is to evaluate the form inside the comment macro (which I define similar to Clojure's comment, to ignore its body).

I have also tried this x.asd file:

(defsystem "x"
  :version "0.1.0"
  :author ""
  :license ""
  :components ((:module "src"
                        :components
                        ((:file "util")
                         (:file "main" :depends-on ("util")))))
  :description ""
  :in-order-to ((test-op (test-op "x/tests"))))

but that doesn't seem to help me with this problem.

Is there a simpler and more standard way to automatically load (or re-compile) util.lisp when I compile main.lisp in the REPL? What's the standard workflow for working with multiple files in the REPL?


Solution

  • Manually this would be:

    File main.lisp

    (eval-when (:load-toplevel :compile-toplevel :execute)
      (load (merge-pathnames "utils.lisp" *load-pathname*)))
    
    (defpackage x.main
      (:use :x.util))
    
    (in-package :x.main)
    
    (foo)
    

    file util.lisp

    (defpackage x.util
      (:use :common-lisp)
      (:export :foo))
    
    (in-package :x.util)
    
    (defun foo () 3)
    

    Then call (load "/my/path/main.lisp").

    More complex stuff would compile the file util.lisp if needed (if there is no compiled file or the lisp file would be newer)... and would then load the compiled code.

    Otherwise you would define a system with two files.

    main.lisp

    (defpackage x.main
      (:use :x.util))
    
    (in-package :x.main)
    

    file util.lisp

    (defpackage x.util
      (:use :common-lisp)
      (:export :foo))
    
    (in-package :x.util)
    
    (defun foo () 3)
    

    Then define an ASDF system "my-system" (util.lisp is needed first and then main.lisp), load that system definition and call (asdf:load-system "my-system")... This would then load all files in the specified order/dependency.