I have this lisp file:
(load "constants.lisp")
(defpackage :my-package
(:use :cl))
(in-package :my-package)
(format t "Constant value: ~A~%" my-constants:+my-constant+)
And this is constants.lisp (same directory):
(defpackage :my-constants
(:use :cl)
(:export :+MY-CONSTANT+))
(in-package :my-constants)
(defconstant +MY-CONSTANT+ "some value")
I get this error when I do C-c C-k on Sly:
There is no package named "MY-CONSTANTS" .
[Condition of type CCL::NO-SUCH-PACKAGE]
How can I load some constant defined in other file? Something like import in other languages. Thanks!!
The problem is that C-c C-k
does not run the file, but compiles it.
So to ensure the loading is executed at compile level, you have to load by:
(eval-when (:compile-toplevel :load-toplevel :execute)
(load "constants.lisp"))
But I think what you actually wanted to do is sly-load-file
just loading the current file.
This you can do by: C-c C-l
and press RETURN when it asks for whether to load this current file's path.
And then, it should work with the simple (load "constants.lisp")
without the eval-when
expression around it!
The only annoying thing will be that you are loading a constant - and therefore it will first activate the handler system (like and error) and ask you what to do, since you are re-loading a constant (constants are not thought to be changed during a session thus also not re-defined).
If it is not absolutely necessary to declare it as a constant, I would just use (defparameter *my-constant* "my value")
and treat it as a special variable which you - by your own convention - doesn't change any more for the rest of the session.
Or, you define (defvar *my-constant* "my value")
and the next time defvar
on the same variable is run - it will be ignored - so it is some kind of a constant - no reloading of the variable.
When you are trying to write a package which loads the my-constants package, then you should use asdf.
With a project structure like
my-project/
│── my-project.asd # ASDF system definition
│── my-constants.lisp # Constants package
│── my-package.lisp # Main package
└── main.lisp # Entry point (optional)
and my-project.asd
:
(asdf:defsystem "my-project"
:description "An example ASDF system with multiple files"
:version "0.1"
:author "Your Name"
:license "MIT"
:depends-on ()
:serial t ;; loading of files in the given order:
:components ((:file "my-constants")
(:file "my-package")
(:file "main")))
my-constants.lisp
:
(defpackage :my-constants
(:use :cl)
(:export +MY-CONSTANT+))
(in-package :my-constants)
(defconstant +MY-CONSTANT+ 42)
my-package.lisp
:
(defpackage :my-package
(:use :cl :my-constants))
(in-package :my-package)
(defun print-constant ()
(format t "Constant value: ~A~%" +MY-CONSTANT+))
And finally main.lisp
with the final package:
(defpackage :my-project
(:use :cl :my-package))
(in-package :my-project)
(defun main ()
(format t "Running my-project...~%")
(print-constant))
;;; Call main automatically when loading:
(main)
Or use if you want to use from main.lisp
also the constants:
(defpackage :my-project
(:use :cl :my-package :my-constants))
(in-package :my-project)
(defun main ()
(format t "Running my-project...~%")
(print-constant)
(format t "Constant: ~A%~%" my-constants:+MY-CONSTANT+))
;;; Call main automatically when loading:
(main)
The most primitive solution and simplest solution would be to manually load both files.
my-loader.lisp
:
(load "my-constants.lisp")
(load "my-package.lisp")
my-constants.lisp
:
(defpackage :my-constants
(:use :cl)
(:export +MY-CONSTANT+))
(in-package :my-constants)
(defconstant +MY-CONSTANT+ 42)
my-package.lisp
:
(defpackage :my-package
(:use :cl :my-constants))
(in-package :my-package)
(defun print-constant ()
(format t "Constant value: ~A~%" +MY-CONSTANT+))
And then finally call in the REPL:
(load "my-loader.lisp")
;; and then you can call
(my-package::print-constant) ;; since not externalized, we use `::`