How to understand this Common Lisp package behavior? - package

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

Related

Common Lisp Package Definition with Dependencies for Exploration at the REPL?

This is another take at the question of packages and systems especially for usage locally in personal projects (maybe similiar to HOWTO definition and usage of Common Lisp packages (libraries)? from 2014). What are recommendations for how to approach this and can links be provided for sources that describe the recommended approach in 2022? CL's long half-life means lots of old blogs and books are still useful, but unfortunately not all of them, and it is hard for the novice to know which are the still viable guides.
Here is the start of a file that I might write for a simple personal exploration project. My basic working mode would be to start slime, load and compile this in emacs, and then change to the slime repl and use in-package to move into my package and start playing with my functions.
(ql:quickload "alexandria")
(ql:quickload "trivia")
(defpackage computing-with-cognitive-states
(:use cl)
(:nicknames :cwcs)
(:local-nicknames (:alex :alexandria)))
(in-package :cwcs)
(defun sum-denom (dimension dist) ... ; and more defun's
The leading ql:quickload's strike me as ugly, but without them I can't load and compile. Is it recommended that I do this manually in slime repl first? Or is this considered an acceptable practice for small use cases like this? Or is there another recommended way?
If I am thinking of using my package elsewhere someday is it recommended that I make it a system, perhaps with quickproject? Or is it the more traditional approach to just load a fasl file from one directory on my system when another session (or another package definition) needs it?
In summary, the questions are about the writing of code that is for personal use, might be a small file, or might be a few files that depend on each other and a few external systems. What are some of the reasonable approaches and resources that describe those approaches? And which are the ones that would be easiest to scale up if the project grew into something that one wanted to share?
For personal one-off »scripts«, I have a little macro in my .sbclrc:
(in-package #:cl-user)
(defmacro ql-require (&rest system-names)
`(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload ',system-names)))
Then my script file looks like this:
(in-package cl-user) ; naked symbols, I don't care much about package pollution here
(ql-require "alexandria" "arrows" …)
(defpackage my-script
(:use cl alexandria arrows))
(in-package my-script)
;; script away!
I open these in Emacs/SLIME, C-c C-k. This often just has the »main« at toplevel, so it will just print at the REPL. In other cases, I hit C-c ~ afterwards to work from the REPL.
As soon as it's not just a script, but something I might want to quickload entirely, I create a simple .asd file for it, which just moves the systems I depend on from the ql-require in the file to the :dependencies in the system definition. The package definition can remain in the one .lisp file. All my common lisp projects are under ~/common-lisp/, which is in the ASDF load path by default. A very simple .asd file can look like this:
(in-package #:asdf-user) ; uninterned symbols as string designators avoid package pollution
(defsystem "my-system" ; system names are lower-case strings
:dependencies ("alexandria" "arrows" …)
:serial t
:components ((:file "my-file")))
The filename for the system definition should be the same as the system name (my-system.asd here). If you put multiple systems into a single file, their names should share the filename as a prefix, optionally followed by a slash and some qualifying suffix (e. g. "my-system" and "my-system/test"). This ensures that ASDF can quickly find the right file to load without having to load it first.
As soon as I split the functionality into several files, I will usually also put the defpackage into its own file.
As soon as I create multiple packages, I will usually create subdirectories for each of them (:modules in :components in the system definition). (ASDF has an option to make a so-called package inferred system, but I prefer the central system definition.)
If you want to share a system, you'd probably want to add an :author and a :license to the system definition (even if it's just CC0/Public Domain). If you think that it's of general interest, you can submit it to Quicklisp.
The simple solution would indeed be to define a system, using ASDF. This is really all that quickproject does, but it is (IMO) a perfectly reasonable solution even for smaller projects.
What you would typically do, assuming you place your code in a somewhat standard location on your system (i.e. you do not have lisp projects everywhere on your file system !), is create a symlink from~/quicklisp/local-projects/ to your/personal/projects/directory. This way, after creating a project with quickproject:make-project (or writing the .asd file by hand ...) in this repository, Quicklisp will be able to find it and you can then quickload it directly, along with its dependencies if you have specified those in the .asd file.
To make things clearer: Quicklisp is "simply" a tool built on top of ASDF which is able to download (and then load) dependencies, and their dependencies ... and so on, if they are specified in a .asd file located in a place it knows. An "equivalent" could be Python's pip. On the other hand, ASDF specifies a way to define systems, that is, a set of source files that should be compiled together, in some specific order, using some dependencies, and so on. On a lower level, this would be more like C/C++'s make or CMake.

Correct way to use the iterate package in Common Lisp

On my Windows XP box with sbcl-1.4.14 I've installed the ASDF using
(load "C:\\Program Files\\clisp-2.49\\asdf\\asdf.lisp")
(require :asdf)
(push "C:\\Documents and Settings\\mayhem\\lisp\\iterate\\" asdf:*central-registry*)
On SLIME
(require :iterate)
(iterate (for i from 1 to 5) (collect (* i i)))
gives The variable I is unbound error
If I do (in-package :iterate), the code above works fine but this time familiar functions such as exit and other functions which I've defined in .sbclrc cease to work, they give The function ITERATE::EXIT is undefined type of errors, for example.
If I do (use-package :iterate), then it gives [Condition of type NAME-CONFLICT] error.
So I began to use the package like this:
(iterate:iterate (iterate:for i from 1 to 5) (iterate:collect (* i i)))
But I think you'll agree that it's a bad style.
How to use the iterate correctly?
Note: I've seen the post about the very similar problem but it didn't help. There aren't many posts or articles about this particular problem.
You need to say (use-package :iterate) before you try to refer to unqualified symbols from the iterate package.
What has happened in your case is this.
You've loaded the iterate system into the running Lisp, creating a package called "ITERATE".
In the "CL-USER" package you've typed (iterate ...), and the reader has worked out that it needs to find or create a symbol whose name is "ITERATE" and which is accessible in the "CL-USER" package.
There is no such symbol, so it creates a new one, CL-USER::ITERATE.
This is not ITERATE:ITERATE so you get an error from the evaluator as it's trying to evaluate the arguments to a function (which doesn't exist, but it doesn't know that yet). In fact the error you're getting is while it's evaluating the first argument in the (for i ...) subform.
Now you say (use-package :iterate) to tell the system to add the "ITERATE" package to "CL-USER"'s search list.
Now there's a conflict: should iterate refer to the existing CL-USER::ITERATE or the newly-accessible ITERATE::ITERATE? (And there are some other conflicts too, probably).
So the system signals an error, and there should be some useful ways to proceed from that, one of which is probably 'unintern all the conflicting "CL-USER" symbols', but you didn't take that option, I suppose.
So now everything is messed up.
And the answer is: use the packages you want to refer to unqualified symbols from before you try to refer to those symbols unqualified.
(Also: Windows XP? I'm impressed by your retroness.)

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.

Changing hunchentoot's current package

I've set up a hunchentoot project with quickproject per Xach's instructions. In-package is run at the top of the file, and hunchentoot is started later in the file. The REPL is switched to my package also, but it is evident that hunchentoot is not running in my package. This causes some disparity between tests in the REPL and the browser. For example there is a function that looks up some stuff in an alist, but hunchentoot gets NILs from it because it is using symbols from another package.
I am aware from the answers to this related question that I can wrap every piece of code that interns symbols in something like
(let ((*package* (find-package :package-name)))
...)
which will set the *package* var to the correct package for the duration of the enclosed code.
Putting this in every function that needs it feels to me like a messy hack.
Intuition says that I should be able to start hunchentoot like this:
(let ((*package* (find-package :package-name)))
(hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 4242)))
So that it makes its whole run with *package* set to the value that I prefer, thereby ensuring that any interning done by a call from the webserver is done in my package. It doesn't work. Hunchentoot ends up interning things under cl-user, possibly due to using a macro like WITH-STANDARD-IO-SYNTAX as in the link above.
Even if I can persuade hunchentoot to do what I want, is there a reason why my 'messy hack' is still the better thing to do?
This is not a Hunchentoot specific question, but relates to Common Lisp packages in general.
What you are seeing is that in your code, the *PACKAGE* special variable is not bound to your own package. IN-PACKAGE changes *PACKAGE* only at compile and read time. When a function in your package is called at run time, *PACKAGE* is not re-bound and needs to be bound explicitly.
When you are using INTERN or FIND-SYMBOL, it is often best to specify the package as argument. Alternatively, you can bind *PACKAGE* yourself.
Try LOADing this file to see:
(defpackage :foo
(:use :cl))
(in-package :foo)
(defun test ()
(print *package*))
(in-package :cl-user)
(foo::test)
Common Lisp code does not 'run' in a package.
There are a few operations which use a default package. Like reading a symbol from a text stream:
CL-USER 1 > *package*
#<The COMMON-LISP-USER package, 56/64 internal, 0/4 external>
CL-USER 2 > (read-from-string "FOO")
FOO
3
CL-USER 3 > (describe (read-from-string "FOO"))
FOO is a SYMBOL
NAME "FOO"
VALUE #<unbound value>
FUNCTION #<unbound function>
PLIST NIL
PACKAGE #<The COMMON-LISP-USER package, 57/64 internal, 0/4 external>
or like finding a symbol:
(find-symbol "FOO")
These operations depend on the value of the variable cl:*package*.
To make sure that these operations (reading symbols, finding symbols, interning symbols, ...) are doing what you expect, you may want to:
set or bind the *package* variable to the package you want to
explicitly pass the package to operations. You can call (find-symbol "FOO") and have *package* set to some package. But you can also call (find-symbol "FOO" my-package) by passing the respective package as an argument.
Summary: Common Lisp code does not 'run in a package', but it uses the variable *package* as a default package for package-related operations. You need to set or bind this variable when you use this mechanism.
When Hunchentoot runs in multi-threaded, its acceptors and handlers are processed in child threads made with bordeaux-threads on non-Lispwork CL implementation. The reason of the situation you asked is that the current packages of child threads become COMMON-LISP-USER.
To get the result you want, you can make child threads' current packages same as calling thread's with implementing START-THREAD generic function corresponding to ONE-THREAD-PER-CONNECTION-TASKMASTER taskmaster.
Note that you use latest Hunchentoot which has START-THREAD generic function, I use of version 1.2.19.
(in-package :hunchentoot)
(defmethod start-thread ((taskmaster one-thread-per-connection-taskmaster) thunk &key name)
(let* (;; calling thread's current package
(package-name (package-name *package*))
;; initial special bindings passed to bordeaux threads
(initial-bindings `((*package* . (find-package ,package-name)))))
;; making child thread passing initial special bindings
(bt:make-thread thunk :name name :initial-bindings initial-bindings)))

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