Gap1512
Gap1512

Reputation: 121

Problem with package communication Common-Lisp

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

Answers (2)

Ehvince
Ehvince

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:

  • as said in a comment, you can use the other package:
    (defpackage :game 
      (:use :cl 
            :cl-ppcre 
            :commands))
    (in-package :game)
  • or call the function with (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

sds
sds

Reputation: 60004

Summary

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.

Details

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:

Files

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))

Nitpicks

Upvotes: 5

Related Questions