Reputation: 121
I have two packages defined: game
(file game.lisp
) and commands
(file commands.lisp
), loaded by a game.asd
file. I'm having trouble in calling commands functions (that have been exported), using the (symbol-function (find-symbol "test-function" 'commands))
, which returns that the function is undefined, even if the (find-symbol "test-function" 'commands)
returned that the function is external, and belongs to the commands
package.
The code on the game.asd
file is:
(asdf:defsystem "game"
:depends-on (#:cl-ppcre)
:components ((:file "game")
(:file "commands")))
The game.lisp
starts with:
(defpackage :game
(:use :cl :cl-ppcre))
The commands.lisp
starts with:
(defpackage :commands
(:use :cl)
(:export "test-function"))
Do I need to use the in-package
function?
From the game.lisp
I call the commands stored in the commands.lisp
file, and some of these calls some functions on the game.lisp
, for example:
(defun test-function ()
(progn
(format *query-io* "Worked!~%")
(start)))
The test-function
is located on the commands package, but calls the start
function, which belongs to the game.lisp
.
I expect the calling of the test-function
function, when I call (symbol-function (find-symbol "test-function" 'commands))
.
Upvotes: 2
Views: 297
Reputation: 18375
I'm not sure why you do the find-symbol
stuff. If you just want to call a function that is defined in another package, you have two options:
use
the other package: (defpackage :game
(:use :cl
:cl-ppcre
:commands))
(in-package :game)
(commands:test-function)
(with a double colon ::
if the function wasn't exported).Here is an example definition for a new project: https://lispcookbook.github.io/cl-cookbook/getting-started.html#creating-a-new-project
see also tips to deal with packages: https://lispcookbook.github.io/cl-cookbook/packages.html
Upvotes: 0
Reputation: 60004
My main recommendation is that you should have separate packages that contain user commands and that contain your Lisp code.
You do not have to create a separate package for each Lisp file you have.
You do need the in-package
macro (it is not a function!) to ensure that your code resides in the
correct package, because
defpackage
merely creates
the package, it does not change
*package*
.
Thus I suggest the following:
game.asd
(asdf:defsystem "game"
:depends-on (#:cl-ppcre)
:components ((:file "package")
(:file "game" :depends-on ("package"))
(:file "commands" :depends-on ("package"))))
package.lisp
(defpackage :game
(:use :cl :cl-ppcre))
game.lisp
(in-package #:game)
...
commands.lisp
(in-package #:game)
...
(defconstant *commands-package* (make-package '#:commands :use nil))
and then use intern
to add
commands to *commands-package*
and find-symbol
to find them.
(defun test-command ()
(format t "test-command~%")
(start))
(intern 'test-command *commands-package*)
You could also define your own macro for that:
(defmacro defcommand (name arglist &body body)
`(progn
(intern (symbol-name ',name) *commands-package*)
(defun ,name ,arglist ,@body)))
(defcommand test-command ()
(format t "test-command~%")
(start))
Do not wrap the function body in an explicit
progn
, because
defun
does that for you.
find-symbol
finds a
symbol
, not a
function
.
Do not forget to string-upcase
the argument to find-symbol
.
Upvotes: 5