Search code examples
packagecommon-lispasdf

Lisp exports internal symbols


I am learning to define a system and have made a small testing package named test. It's structure looks like the following:

test/
  test.asd
  hi.lip
  hito.lisp
  package.lisp

Now in package.lisp file i define my package:

(in-package :cl-user)

(defpackage :test
  (:use #:cl)
  (:import-from #:uiop
        #:strcat)
  (:export #:sayhito))

and in test.asd the system:

(defsystem test
  :name "Testing"
  :components ((:file "package")
           (:file "hi")
           (:file "hito")))

In hi.lisp i have a helper function sayhi which isn't meant to be external:

(in-package :test)

(defun sayhi () "Hi")

and in hito.lisp the external function of the system hito:

(in-package :test)

(defun sayhito (name)
  (strcat (sayhi) " " name "!"))

I also have a directory /home/amir/lisp-link-farm/ where i put symbolic links of all my ASDFs into. Then in my lisp initialization file (.sbclrc) i have pushed this path into asdf:*central-registry*:

;;; The following lines added by ql:add-to-init-file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
                                   (user-homedir-pathname))))
  (when (probe-file quicklisp-init)
    (load quicklisp-init)))


;; where i am restoring symlinks to systems
(require 'asdf)
(push #p"/home/amir/lisp-link-farm/" asdf:*central-registry*)

Now when i load the test system by (ql:quickload :test) and change the package to (in-package :test) the internal helper function hi is also accessible as an external symbol! I can just do:

(sayhi)   ;; -> "Hi"

But if i don't change the package (so without (in-package :test) in the REPL) trying to call (test:sayhi) lisp complains that sayhi is not an external symbol in package test, while (test:sayhito "Lisp") works as it should. Why is this happening and what am i doing wrong? Any help is appreciated.


Solution

  • No, it is not accessible as an external symbol. As you wrote yourself, you changed the package to the package in question, and that means that it is your current package, and all symbol resolution works internally. It is just the same as when you write code in a specific package: you can refer to all symbols of the package without prepending the package.

    Note that even if you changed your current package to test, referring to test:hi (with a single colon) signals an error.

    So, you are not doing anything wrong, except expecting that the REPL somehow had other package resolution rules than a source file.