Common lisp — why isn't this symbol external? - package

I'm trying to run tests in ASDF, which looks like this:
;;;; foo.asd
(defsystem "foo/tests"
:depends-on ("foo"
"fiveam")
:components ((:module "tests"
:components
((:file "main"))))
:perform (test-op (op c) (symbol-call :fiveam '#:run! 'foo/tests:all-tests))
And my tests/main.lisp file starts off like this:
;;;; tests/main.lisp
(defpackage foo/tests
(:use :cl
:foo
:fiveam)
(:export :#run! :#all-tests))
(in-package :foo/tests)
When I run (asdf:test-system 'foo) in my REPL, I get dropped into the debugger with a LOAD-SYSTEM-DEFINITION-ERROR. The debugger is complaining that The symbol "ALL-TESTS" is not external in the FOO/TESTS package.
However, I am clearly exporting the symbol in the foo/tests package. Can somebody please tell me what I'm missing here and why the Lisp compiler isn't seeing the external symbol? Thank you very much.

The syntax for an uninterned symbol is #:foo, not :#foo.
You also need to resolve the symbols in the :perform form at run-time, e. g. through uiop:find-symbol*, just like you use uiop:symbol-call there.
:perform (test-op (op c)
(symbol-call :fiveam '#:run!
(find-symbol* '#:all-tests '#:foo/tests)))
Or, since you seem to export a run! function from your test package, you might want to call that instead of fiveam:run!:
:perform (test-op (op c)
(symbol-call '#:foo/tests '#:run!))

Related

How to understand this Common Lisp package behavior?

I am new to Common Lisp. Even more when the topic is packages and systems. I am working with a program and something intrigues me. Btw, I am using SBCL and Slime (Emacs).
Being on the top-level (CL-USER) I can do:
CL-USER> (application-name/file-name::%function-on-parenscript)
This works! Then, I change to be inside the package:
CL-USER> (in-package :application-name)
Ok. So, I thought that after being inside the application name:
APPLICATION-NAME>
I would be able to do just:
APPLICATION-NAME> (file-name::%function-on-parenscript)
However, this does not work. It just works if I do:
APPLICATION-NAME> (application-name/file-name::%function-on-parenscript)
1 - Why is the application-name necessary if I am inside application-name?
2 - Why sometimes I need to use :: and other times I use just : to call things?
Common Lisp packages are there to solve namespaces problems. But they really intrigue me.
application-name/file-name and application-name are two distinct packages that are similar in names only for human readers but are otherwise unrelated.
Symbols are either written with a package prefix or not. The package is the part on the left of the colon or double-colon when there's a package prefix.
The double colon is a way to refer to symbols that are not exported from the package (they are private).
A single colon is for symbols that are exported.
If the symbol you want to refer is "accessible" in the current package, for example because you are "using" it's package and it is exported, then you can write the symbol without a package prefix
See Programming in the Large: Packages and Symbols for details

:EXPORT from Package in Common Lisp

I have defined a package like the following:
(defpackage :thehilariouspackageofamirteymuri
(:nicknames ampack amir teymuri)
(:use common-lisp)
(:export say-hi-to))
(in-package :amir)
(defun say-hi ()
"Docstring"
"Hello")
(defun say-hi-to (who)
(concatenate 'string (say-hi) " " who " from " (package-name *package*) "!"))
Now changing to the package also the #'say-hi is accessible:
(in-package :amir)
(say-hi) ; -> "Hello"
(say-hi-to "World") ; -> "Hello World from THEHILARIOUSPACKAGEOFAMIRTEYMURI!"
Isn't the export keyword telling to make things external for the package? Why is the non-external #'say-hi also exported?
Since you are using again (in-package :amir) the following forms are evaluated in that package, so that you can use all the function defined in it. To check which definitions are exported, you should switch to a different package.
Let’s try the standard package CL-USER:
AMIR> (in-package :cl-user)
#<Package "COMMON-LISP-USER">
CL-USER> (say-hi)
Undefined function SAY-HI called with arguments ("world") ; as expected, but...
CL-USER> (say-hi-to "world")
Undefined function SAY-HI-TO called with arguments ("world") ; ops!!
CL-USER> (amir:say-hi-to "world)
"Hello world from COMMON-LISP-USER!"
CL-USER> (amir:say-hi)
Reader error: No external symbol named "SAY-HI" in package #<Package "THEHILARIOUSPACKAGEOFAMIRTEYMURI"> .
The reason is that exporting a symbol does not mean that we can use it without qualiyfing its package. As you can see, however, only symbols exported from a packgage can be used with “:”. If you want to use the symbol without the package name as prefix, you must import it before.
So, let’s start again.
CL-USER> (defpackage :another-package (:use :amir))
#<Package "ANOTHER-PACKAGE">
CL-USER> (in-package :another-package)
#<Package "ANOTHER-PACKAGE">
ANOTHER-PACKAGE> (say-hi-to "world")
"Hello world from ANOTHER-PACKAGE!"
ANOTHER-PACKAGE> (say-hi)
Undefined function SAY-HI called with arguments ()
Inside ANOTHER-PACKAGE you can now use the exported symbol without qualifications.
In general, exporting and importing symbols in packages in Common Lisp is not so intuitive, and a good description of all the intricacies of packages can be found at the link cited in the other answer.
Check the difference without changing the current package. You will find more information e.g. here

Suppressing Symbol Package Prefixes (Common Lisp)

When printing out object names which are interned in one package, but referenced from another package, the print name will include the full package name. For example, the following interaction interns the symbol X in PKG1, and prints its value from CL-USER:
* *package*
#<PACKAGE "COMMON-LISP-USER">
* (defpackage :pkg1 (:use :cl))
#<PACKAGE "PKG1">
* (in-package :pkg1)
#<PACKAGE "PKG1">
* (defvar x '(a b c))
X
* (in-package :cl-user)
#<PACKAGE "COMMON-LISP-USER">
* pkg1::x
(PKG1::A PKG1::B PKG1::C)
Sometimes for diagnostic/debugging reasons, I would like to printout external symbols without their package prefixes. In this case the printout would then look like (A B C). For complicated or nested objects where you know what the names mean, the package prefixes can make the printout hard to read, especially if there are multiple packages. Can the prefixes be temporarily suppressed for printout?
No, but you can elide the prefixes of one package by temporarily binding *package* to it for the printout.
Example:
(let ((*package* (find-package :pkg1)))
(print pkg1:*x*))
Since *package* is globally dynamic, this affects everything called inside (i. e. in the dynamic extent of its invocation) this let form but doesn't affect anything outside.

Why isn't asdf:load-system creating the package

I'm trying to to use asdf's functionality to run my test suite from the repl but when using quicklisps quickload if fails on the first attempt to load foo and success on the second.
(in-package :cl-user)
(defpackage :foo-system
(:use :cl :asdf))
(in-package :foo-system)
(asdf:defsystem :foo
:components ((:file "foo")))
(asdf:defsystem :foo-tests
:depends-on (:foo)
:components ((:file "foo-tests")))
(defmethod asdf:perform ((op test-op) (system (eql (find-system :foo))))
(asdf:load-system 'foo-tests)
(foo-tests:run-tests))
It makes sense because when I compile the asd file the error appears to be in the second form of the asdf:perfom defmethod. The error, replacing nclack by foo, is:
../../nclack/nclack.asd:36:27: read-error:
READ error during COMPILE-FILE:
Package NCLACK-TESTS does not exist.
Line: 36, Column: 27, File-Position: 1034
Stream: #<SB-SYS:FD-STREAM
for "file /Users/PuercoPop/quicklisp/local-projects/nclack/nclack.asd"
{1005DB11A3}>
which matches the (foo-tests:run-tests) line. So it appears to be that 'loading' a system is different from compiling its forms? Or why is the package not defined after loading the system? Any ideas? I'm at a loss.
When you compile-file this:
(defmethod asdf:perform ((op test-op) (system (eql (find-system :foo))))
(asdf:load-system 'foo-tests)
(foo-tests:run-tests))
the first step is to read the entire form. Reading includes interning of all symbols found. However, at read time, the form has not executed, so the system foo-tests is not yet loaded. Since that system includes the package foo-tests, and that is not loaded yet either, you cannot intern any symbols into that package at read time of this form.
That's why compile-file gives the error shown when trying to read the form.
It seems to me that you would need to (funcall (find-symbol "RUN-TESTS" #:foo-tests)).
First:
If you define a new package FOO-SYSTEM and use the package ASDF and then use the asdf symbols still with the prefix, then you kind of defeated the using of the package. Why use it, when you prefix the symbols anyway?
It is hard to say what the error is, since we don't see a backtrace and don't see the files.
Anyway, you need to make sure that a package is available during compilation of a file. For example compiling a DEFPACKAGE form may not change the compile-time environment. You need to execute the DEFPACKAGE form. You also need to make sure that the package definition gets loaded during a load system operation.
If the package does not exist, you need to make sure that it exists.

CLisp: "use-package" resolving conflicts non-interactively

I'm trying to use parenscript in GNU common lisp to compile a lisp file into a javascript one.
I find that using the PS symbol macro "#" doesn't work if I try to use its prefix ("ps:#"). However, if I use the REPL and run (use-package :ps) before I try compiling the lisp file, everything works as expected (and I don't have to use the prefixes).
The problem is that the PS package contains clashing symbols, e.g:
*** - (USE-PACKAGE (#<PACKAGE PARENSCRIPT>) #<PACKAGE COMMON-LISP-USER>): 2 name conflicts remain
Which symbol with name "CHAIN" should be accessible in #<PACKAGE COMMON-LISP-USER>?
The following restarts are available:
PARENSCRIPT :R1 #<PACKAGE PARENSCRIPT>
COMMON-LISP-USER :R2 #<PACKAGE COMMON-LISP-USER>
ABORT :R3 Abort main loop
I can resolve this interactively by choosing :r1, but when I try to put this step in my script it just bails (since it's non-interactive, it doesn't give me a choice of what restart to use)
I'd love to say (in my script) "just use the PS version of all clashing symbols", but I can't figure out how to do so.
It would also be okay if I could say (as one might in python), "from PS import chain, #, (etc)" - specifying each symbol I want to import manually.
Instead of working in the COMMON-LISP-USER package, make your own with DEFPACKAGE:
(defpackage #:my-awesome-program
(:use #:cl #:parenscript))
(in-package #:my-awesome-program)
; your code here
COMMON-LISP-USER might include all sorts of implementation-specific symbols.
You can also use SHADOWING-IMPORT to get individual symbols, overriding what might already be currently visible in the package, e.g.
(shadowing-import 'ps:*)

Resources