Проблема с пакетной связью Common-Lisp - PullRequest
0 голосов
/ 16 января 2019

У меня определены два пакета: game (файл game.lisp) и commands (файл commands.lisp), загруженный файлом game.asd. У меня проблемы с вызовом командных функций (которые были экспортированы) с использованием (symbol-function (find-symbol "test-function" 'commands)), который возвращает, что функция не определена, даже если (find-symbol "test-function" 'commands) вернул, что функция является внешней и принадлежит к commands пакет.

Код в файле game.asd:

(asdf:defsystem "game"
  :depends-on (#:cl-ppcre)
  :components ((:file "game")
               (:file "commands")))

game.lisp начинается с:

(defpackage :game
  (:use :cl :cl-ppcre))

commands.lisp начинается с:

(defpackage :commands
  (:use :cl)
  (:export "test-function"))

Нужно ли использовать функцию in-package? Из game.lisp я вызываю команды, хранящиеся в файле commands.lisp, а некоторые из них вызывают некоторые функции в game.lisp, например:

(defun test-function ()
  (progn
    (format *query-io* "Worked!~%")
    (start)))

test-function находится в пакете команд, но вызывает функцию start, которая принадлежит game.lisp.

Я ожидаю вызова функции test-function, когда я вызываю (symbol-function (find-symbol "test-function" 'commands)).

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Я не уверен, почему вы делаете вещи find-symbol. Если вы просто хотите вызвать функцию, определенную в другом пакете, у вас есть две опции:

  • Как сказано в комментарии, вы можете use другой пакет:
    (defpackage :game 
      (:use :cl 
            :cl-ppcre 
            :commands))
    (in-package :game)
  • или вызов функции с помощью (commands:test-function) (с двойным двоеточием ::, если функция не была экспортирована).

Вот пример определения для нового проекта: https://lispcookbook.github.io/cl-cookbook/getting-started.html#creating-a-new-project

см. Также советы по работе с пакетами: https://lispcookbook.github.io/cl-cookbook/packages.html

0 голосов
/ 16 января 2019

Резюме

Моя основная рекомендация - иметь отдельные пакеты, содержащие пользовательские команды и код вашего Лисп.

Вы не должны создавать отдельный пакет для каждого файла Lisp, который у вас есть.

Подробнее

Вам нужен in-package macro (это не функция !), Чтобы гарантировать, что ваш код находится в правильный пакет, потому что defpackage просто создает пакет, он не изменить *package*.

Таким образом, я предлагаю следующее:

Файлы

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

, а затем используйте intern для добавления команды *commands-package* и find-symbol, чтобы найти их.

(defun test-command ()
  (format t "test-command~%")
  (start))
(intern 'test-command *commands-package*)

Вы также можете определить свой собственный макрос для этого:

(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

...