Quickload inside eval-when - common-lisp

Here's a strange situation. I have this code:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload "cffi-grovel")
(setf cffi-grovel::*cc* "mpicc")) ; <--- this is the line it complains about.
Which I belive has to load cffi-grovel package before setting cffi-grovel::*cc* variable. When this form is executed from SLIME it works, but it doesn't work when loaded directly by SBCL, here's the output:
$ sbcl --noinfo
* (ql:quickload "cl-mpi")
debugger invoked on a LOAD-SYSTEM-DEFINITION-ERROR in thread
#<THREAD "main thread" RUNNING {10029C0E43}>:
Error while trying to load definition for system cl-mpi from pathname
/home/wvxvw/quicklisp/local-projects/cl-mpi/cl-mpi.asd:
READ error during COMPILE-FILE:
Package CFFI-GROVEL does not exist.
Line: 6, Column: 25, File-Position: 264
< restarts ... >
* (ql:quickload "cffi-grovel")
To load "cffi-grovel":
Load 1 ASDF system:
cffi-grovel
; Loading "cffi-grovel"
..
("cffi-grovel")
* (ql:quickload "cl-mpi")
To load "cffi-grovel":
Load 1 ASDF system:
cffi-grovel
; Loading "cffi-grovel"
To load "cl-mpi":
Load 1 ASDF system:
cl-mpi
; Loading "cl-mpi"
; mpicc -m64 ...
; ...
.
("cl-mpi")
Why does it fail the first time?
PS. I also tried #.cffi-grovel::*cc* instead - same result.

It fails because Lisp reads every form before executing it. And when it reads it, package cffi-grovel indeed does not exist yet, because cffi-grovel is loaded at execution time (whatever it means for form wrapped with eval-when).
Try spliting the eval-when form into two eval-whens: ql:quickload and setf. Or write something like this:
(setf (symbol-value (find-symbol "*CC*" "CFFI-GROVEL"))
"mpicc")

monoid gives a good answer. Here is a slightly shorter form.
Find the symbol at runtime, when the package actually exists. Note the use of SET, not SETF here:
(set (find-symbol "*CC*" "CFFI-GROVEL") "mpicc")
To make it more robust, one would need to check that FIND-SYMBOL actually finds the symbol.
The following function also gives you meaningful error messages and restarts:
(defun set-runtime-symbol (name package value)
(assert (find-package package) (package))
(assert (find-symbol name package) (name))
(set (find-symbol name package) value))
Alternatively use two EVAL-WHEN statements, instead of one.

OK, finally figured it I can do it like so:
(setf #.(intern "cffi-grovel::*cc*") "mpicc")
But I'm not sure how much this is fail-safe.

Related

Error: Unbound variable: *AJAX-PROCESSOR* using HT-SIMPLE-AJAX

I'm using HT-SIMPLE-AJAX to provide a simple JSON structure over AJAX. It works beautifully if the function defined by defun-ajaxis compiled after the lisp image and the server is started.
If I load the lisp program (with ccl --load) with the function defined, I get this error:
Error: Unbound variable: *AJAX-PROCESSOR*
While executing: #, in process listener(1).
Type :GO to continue, :POP to abort, :R for a list of available restarts.
If continued: Skip loading "/home/hunchentoot/quicklisp/local-projects/gac-man/run.lisp"
Type :? for other options.
The function is as follows:
(defun-ajax machine-info (serial) (*ajax-processor*)
(let* ((serialn (remove #\" serial)))
(concatenate 'string
"Lots of boring stuff" "here")))
The ajax processor is created in another function, called at the start of the program:
(defun start ()
(setup)
(connect-to-database)
(defvar *web-server* (start (make-instance 'hunchentoot:easy-acceptor :port 8080
:document-root #p"~/www/")))
(defvar *ajax-processor*
(make-instance 'ajax-processor :server-uri "/ajax"))
(print "Starting web server...")
(setf *show-lisp-errors-p* t
*show-lisp-backtraces-p* t)
(define-easy-handler (docroot :uri "/") () (docroot)
....
....
(setq *dispatch-table* (list 'dispatch-easy-handlers
(create-ajax-dispatcher *ajax-processor*)))))
And yet if I start everything and then compile in the function through slime later, it works just fine. Why is this error occurring?
I'm using Clozure Common Lisp on 64-bit Linux.
It seems that your defun-ajax form is loaded before the start function has run. That is not surprising. Usually, all code is loaded, and only then the entry point is called.
You should always be very suspicious of defvar, defun, defparameter etc. forms appearing in a function body. They don't belong there. Put them as toplevel forms, so they are loaded as part of the program. Most of the things defined during the run of the start function shown should really be toplevel forms.

Bulk `unintern` for renamed exported symbols

I use packages a lot and the exported symbols often change their names. When I try to recompile the package I get warnings like this:
package.lisp:3:1:
warning:
MY-PROJECT also exports the following symbols:
(OLD-SYMBOL1 OLD-SYMBOL2 OLD-SYMBOL3)
See also:
Common Lisp Hyperspec, DEFPACKAGE [:macro]
SBCL Manual, *ON-PACKAGE-VARIANCE* [:variable]
--> EVAL-WHEN
==>
(SB-IMPL::%DEFPACKAGE "MY-PACKAGE" '("KE") 'NIL 'NIL 'NIL '("CL") 'NIL
'NIL '("NEW-EXPORTED-SYMBOL1" "NEW-EXPORTED-SYMBOL2") '("MY-PROJECT") 'NIL
...)
I know that I can use (unintern 'old-symbol1) to signal the system I don't want to use that symbol anymore. However this is becoming very tedious when there is a lot of renaming.
My questions are:
1) Is is possible to signal to sbcl or emacs to unintern the old/previously exported symbols automatically?
2) If not - is it possible to get all "old" symbols in a variable?
My plan for 2) is to make a key binding to something like (apply #'unintern *old-symbols*)
Setting the variable *on-package-variance* to a list (:error t) will give you an error instead of a warning when redefining the package. The error will have a restart DROP-THEM to unexport the symbols.
You can add
(setf *on-package-variance* '(:error t))
to your ~/.sbclrc to have it always set when starting up SBCL.
First I don't think you want to unitern symbols. Unintern removes them from the package. I think you want to unexport them to avoid the warning. You can do that with the following function
(defun unexport-package-symbols (package)
(do-symbols (symbol package)
(destructuring-bind (symbol status)
(find-symbol (symbol-name symbol) package)
(when (eq status :external)
(cl:unexport symbol package)))))
;; It takes a package-designator as an argument.
(unexport-package-symbols "MY-PACKAGE")

lexical binding lost when switching package

All I wanted was to load an initialisation file for swank which wouldn't affect my lisp when it's started without swank...
I first tried #+swank (defun...) in my file that's loaded from ccl-init (trying this on ccl 1.10 + windows), and soon realised it's sourced before swank is loaded (obviously).
My aim is to define a simple function in :cl-user everytime I start swank. I just ended up with a swank add-hook to load my init.lisp file, and since I want to define the function in cl-user, I tried this in the init.lisp:
(let ((current-package *package*))
(in-package :cl-user)
(defun cd (dir)
(swank:set-default-directory
(parse-namestring dir)))
(in-package current-package))
Now, I don't recall if a defun in let was allowed, but lisp doesn't complain for it, but rather tells me that cur-pck symbol doesn't exist, and it seems when we switch the package, cur-pck binding gets out of scope. I thought cur-pck is a lexical binding, and that it should be reachable from within the lexical region, being independent from a package, am I wrong?
Why do I switch packages? I'm thinking that loading this file from swank at some initialisation point will define things in some swank package, that's why I wanted to try switching to cl-user first, define the function symbol, and switch back to let swank do it's thing.
At this point I guess I need someone to tell me I'm approaching the problem from the wrong angle, and that I should better choose an easier solution.
Additionally, out of curiosity in case above is the complete wrong approach, is there a way to define a symbol in another package within a function or a closure?
Switching packages in a form has no direct effect on the form
Let's look at this:
(in-package "FOO")
(let ((x 10))
(in-package "BAR")
(setf x 20))
Which x does it set to 20? FOO::X or BAR::X?
Well, it is FOO::X. Switching packages during execution has no effect on the symbols already read. The whole let form is read at once and the *package* value is used for that. Having an IN-PACKAGE in the form itself has no effect on the form itself.
Symbol with a package prefix
If you want to use a symbol in a certain package, just write the package prefix:
cl-user:foo ; if FOO is exported and the package exists
or
cl-user::foo ; if foo is not exported and the package exists
for example:
(defun cl-user::cd (...) ...)
Computing with symbols
You can also compute new symbols in packages you don't know yet:
(let ((sym-name "A-NEW-SYMBOL")
(my-package-name "SOME-EXISTING-PACKAGE"))
(intern sym-name my-package-name))
If the package does not exist, you can create it.
You can also set the function of a computed symbol:
(setf (symbol-function (compute-a-function-symbol))
#'(lambda ()
'foo))
If you want to define a function in a different package that the current one you can use a qualified symbol for a name
(defun cl-user::cd (dir)
(swank:set-default-directory
(parse-namestring dir)))
The binding is not being "lost". To test so yourself add (princ cur-pck) before the in-package form.
If you try evaluating (in-package *package*) you will see why your code fails to switch packages. The in-package macro does not evaluate its argument. The code that would give us the code we would want to evaluate is:
(let ((cur-pck *package*))
(in-package :cl-user)
(defun cd (dir)
(swank:set-default-directory
(1+ 2)))
(princ cur-pck)
`(in-package ,cur-pck))
However, as Rainer Joswig noted in his answer the in-package has no effect on forms already read, so it wouldn't work as desired even as a macro.
A style nitpick, don't use abbreviations, write current-package.
IN-PACKAGE is a macro, not a function. The problem in your code is that saying (in-package cur-pck) tries not to switch into the package denoted by the cur-pck variable but to the package named CUR-PCK (which obviously does not exist).
You can set the package temporarily with
(let ((*package* (find-package :cl-user)))
(defun cd (dir)
...))
But then again, the easiest way to achieve what you are doing would be
(defun cl-user::cd (dir)
...)
which totally eliminates the need to set the current package.

Function invisible from macrolet? [duplicate]

I put failing.asd
(in-package :asdf-user)
(defsystem "failing"
:description "some code destined to fail"
:version "0.1"
:author "me"
:components ((:file "package")))
and package.lisp
(defpackage :failing
(:export :foo :bar))
(in-package :failing)
(defun foo () 42)
(defmacro bar ()
(let ((x (foo)))
`(print ,x)))
(bar)
into ~/quicklisp/local-projects/failing. Using Clozure CL with Quicklisp installed, I run
(ql:quickload :failing)
which gives me
To load "failing":
Load 1 ASDF system:
failing
; Loading "failing"
[package failing]
> Error: Undefined function FOO called with arguments () .
> While executing: BAR, in process listener(1).
> Type :GO to continue, :POP to abort, :R for a list of available restarts.
> If continued: Retry applying FOO to NIL.
> Type :? for other options.
It seems I can't call a function from a macro inside the package. Why not?
That can only happen when the file gets compiled before loaded. Generally it has nothing to do with ASDF (which is a tool to manage file dependencies and to compile/load code) or packages (which are namespaces and are not in any way related to ASDF).
It has to do with how file compilation works in Common Lisp:
The file compiler sees the function foo and compiles it -> the code for it gets written to a file. It does not (!) load the code into the compile-time environment.
The file compiler then sees the macro bar and compiles it -> the code gets written to a file. It does (!) load the code into the compile-time environment.
The file compiler then sees the macro form (bar) and wants to expand it. It calls the macro function bar. Which calls foo, which is undefined, since it is not in the compile-time environment.
Solutions:
put the function definition in a separate file in the ASDF system and compile/load it earlier.
put the function inside the macro as a local function
put (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE) ...) around the function definition. It causes the definition to be executed at compile-time.
Remember: the file compiler needs to know macro functions -> otherwise it would not be able to macroexpand code. Ordinary functions just get compiled, but not loaded at compile time, during compilation of a file.

On Slime Load , change default package from Cl-USER

When we start slime, it starts in CL-USER by default. Since I work with a particular package very frequently, I want to automatically in-package into that package on slime startup.
i.e. I want save myself the trouble of doing the below:
CL-USER> (ql:quickload :my-package)
CL-USER> (in-package my-package)
MY-PACKAGE>
I tried putting the following code in my ccl-init.lisp file but the in-package did not work:
(ql:quickload :my-package)
(in-package my-package)
You probably could do something with slime-repl-mode-hook
But I think it would be better to use the slime-sync-package-and-default-directory which is bound to C-c ~ and syncs your REPL to the package of your buffer.

Resources