How to make Lisp forget about previously exported symbols? - lisp

This is how I export symbols :bar and :baz from package foo:
(in-package :cl-user)
(defpackage foo
(:use :cl)
(:export :bar :baz))
(in-package :foo)
When I remove :baz from the list of exported symbols SBCL complains and the compilation fails.
warning:
FOO also exports the following symbols:
(FOO:BAZ)
How can I make SBCL make forget about :baz without reloading SLIME?

SBCL:
* (apropos "unexport")
UNEXPORT (fbound)
* (documentation 'unexport 'function)
"Makes SYMBOLS no longer exported from PACKAGE."
* (apropos "unintern")
UNINTERN (fbound)
* (documentation 'unintern 'function)
"Makes SYMBOL no longer present in PACKAGE. If SYMBOL was present then T is
returned, otherwise NIL. If PACKAGE is SYMBOL's home package, then it is made
uninterned."

Search led me here, but I had slightly different issue.
; caught WARNING:
; MY-PACKAGE also uses the following packages:
; (DEPENDENCY)
For this case, one needs
* (documentation 'unuse-package 'function)
"Remove PACKAGES-TO-UNUSE from the USE list for PACKAGE."

There is plenty of documentation on these issues, which you should read or reread. This package/symbol thing sounds trivial enough at first sight, but it is different enough from what other languages do to be worth some reading (i.e. trying to reuse knowledge from other languages is particularly risky when it comes to packages and symbols).
If, after reading the docs, you still have trouble, try rereading them (the experience gained by having trouble will help you focus on the relevant sections; rereading without getting into trouble between readings is not very productive IMHO).
Some links I found useful:
http://www.lispworks.com/documentation/HyperSpec/Body/11_.htm
http://www.gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html
http://www.flownet.com/ron/packages.pdf

Related

Why does Lisp code execute if entered line by line in the REPL but not if compiled in the buffer?

I am a noob Lisper and am attempting Adam Tornhill's Lisp for the Web tutorial using Portacle Emacs.
I would very much appreciate an explanation of why the set-up code below will run happily and change the REPL cursor to RETRO-GAMES> if entered line by line in the REPL but does not seem to work if compiled in the buffer. (The first time it compiles it often throws an error saying it can't find the quickload packages; the REPL cursor never changes.)
If anyone can shed light on what this implies for compiled programs, it would be great. I'm struggling to understand the value of programming directly into a REPL rather than a saved file. If there are any noob-level resources on what a fully compiled program "looks like" in terms of whether it includes the type of loady code below, a link would make my day. Thank you.
(load "C:/Users/USER/portacle/all/quicklisp/quicklisp/setup.lisp")
(ql:quickload :cl-who)
(ql:quickload :hunchentoot)
(ql:quickload :parenscript)
(defpackage :retro-games
(:use :cl :cl-who :hunchentoot :parenscript))
(in-package :retro-games)
(defclass game ()
((name :initarg :name)
(votes :initform 0)))
To see why this code is a problem for compilation, consider what the compiler must do when compiling a file containing it, in a 'cold' Lisp image, where 'cold' here specifically means 'without Quicklisp loaded'. To see this, divide it into chunks. For the sake of argument we'll imagine that the way the file compiler works is to read a form from the file, compile it, and write it out. It does have to work in a way which is equivalent to this for our purposes so that's OK here.
First chunk
(load "C:/Users/USER/portacle/all/quicklisp/quicklisp/setup.lisp")
load is a normal function and the call to it occurs at top level in the file: what the compiler will do is to compile code so that, when the file is loaded this load is called. The compiler will not itself execute load, and so Quicklisp will not be loaded at compile time.
Second chunk
(ql:quickload :cl-who)
(ql:quickload :hunchentoot)
(ql:quickload :parenscript)
This code has two problems. In a cold lisp the QL package does not exist, because the previous load was not executed at compile-time, so the reader will raise an exception when reading these forms. Compilation will stop here.
If the Lisp is not cold and in particular if the QL package does exist (so, if the Lisp image which is doing the compilation does have Quicklisp loaded into it) then the compiler will simply write code which causes these three ql:quickload calls to take place at load-time, and will not load these three QL systems now.
In a cold lisp you will not get beyond this step. In a Lisp with Quicklisp loaded at compile time you will.
Third chunk
(defpackage :retro-games
(:use :cl :cl-who :hunchentoot :parenscript))
This chunk will only be reached in a Lisp where Quicklisp is loaded at compile time. This is a package definition, and it has effect at compile time, as it must do. But, at compile time, the calls in the second chunk have not yet taken place: this package definition refers to packages which do not exist. So this is a compile-time error and compilation will stop here.
If the Lisp doing the compilation not only has Quicklisp loadad but also has the three QL systems loaded, this will succeed.
Fourth chunk
(in-package :retro-games)
This will only be reached in a lisp which, at compile time, has both Quicklisp and the three QL systems loaded into it. In that case it tells the compiler that the following forms are to be read in the retro-games package. Otherwise it is never reached.
Fifth chunk
(defclass game ()
((name :initarg :name)
(votes :initform 0)))
In the unlikely event the compiler gets this far, this defines a class called retro-games::game.
What the problem is
The problem is that the compiler is, well, a compiler: what it does is compile code for later execution. But the later parts of your source depend on the earlier parts of your source having been loaded.
There are two ways to deal with this.
If you are only writing a very small amount of code, then you can tell the compiler that some things must happen at compile time as well as at load time. The way you do this is by eval-when, and the particular incantation you want is something like this, for chunks one and two:
(eval-when (:compile-toplevel :load-toplevel :execute)
(load "C:/Users/USER/portacle/all/quicklisp/quicklisp/setup.lisp"))
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :cl-who)
(ql:quickload :hunchentoot)
(ql:quickload :parenscript))
Note you must have two separate incantations of eval-when because the QL package needs to be brought into being by the first so that the second can be read.
The semantics of eval-when are mildly hairy, but this incantation will do what you want: it will tell the compiler to load these things and make sure that they are also run at load time.
The second way of dealing with this, which is appropriate for larger systems, is to have one or more files which build the compile-time environment for later files, and which are compiled and loaded before the later files, under the control of something like ASDF. In this case you typically want some minimal bootstrap file, which perhaps simply needs to make sure that Quicklisp is loaded and then ask Quicklisp (and hence ASDF) to compile and load everything else, with dependency management looked after by those tools, so there would be no ql:quickloads at all. How to set up something like this is beyond this answer however!

undefined operator after quickload lisp

The function find-data-from-command works fine when I run it without first doing the 'quickload' of the package. If I load the package it gives the error that split-sequence is undefined.
I have tried to reload split-sequence after loading the custom package. Doesn't work
(ql:quickload :<a-custom-package>)
(defun find-data-from-command (x desired-command)
(setq desired-data ())
(loop for line = (read-line x nil)
while (and line (not desired-data)) do
(progn
(setq commands (first (split-sequence ":" line)))
(setq data (split-sequence "," (first (rest (split-sequence ":" line)))))
(print (cons "command:" commands))
(cond
((equal commands desired-command) (return-from find-data-from-command data))))))
FIND-DATA-FROM-COMMAND
SIGMA 24 >
(setq obj-type (find-data-from-command (open "log.txt") "types"))
Error: Undefined operator SPLIT-SEQUENCE in form (SPLIT-SEQUENCE ":" LINE).
The problem is nothing to do with Quicklisp, it's to do with a package you've defined somewhere called SIGMA. In particular somewhere in your code is a form which looks like:
(defpackage "SIGMA" ;or :sigma or :SIGMA or #:sigma or ...
...
(:use ...)
...)
And then later
(in-package "SIGMA")
And the problem with this is that your package definition has an explicit (:use ...) clause.
defpackage, and the underlying function make-package has slightly interesting behaviour for the :use clause (or keyword argument in the case of make-package):
if none is given then there is an implementation-defined default;
if one is given then it overrides the default.
The idea, I think, is that implementations may want to provide a bunch of additional functionality which is available by default, and this functionality can't be in the CL package since the contents of that package is defined in the standard. So if you just say
(defpackage "FOO")
Then the implementation is allowed (and, perhaps, encouraged), to make the use-list of FOO have some useful packages in it. These packages might be the same ones that are in the default use-list of CL-USER, but I'm not sure that's required: the whole thing is somewhat under-specified.
The end result of this is that if you want to define packages which both make use of implementation-defined functionality and have explicit use-lists you have to resort to some slight trickery. How you do this is slightly up to you, but since you are by definition writing implementation-dependent code where you are defining packages like this, you probably want to make it clear that what you are doing is implementation-dependent, by some form like
(defpackage :foo
(:use ...)
#+LispWorks
(:use :lispworks :harlequin-common-lisp :cl)
...)
Or, if you just want some particular set of symbols
(defpackage :foo
(:use ...)
#+LispWorks
(:import-from :lispworks #:split-sequence))
Note that this is not quite the same thing as using a package containing the symbol.
In all these cases if your code has pretensions to be portable then there should be appropriate clauses for other implementations and a way of knowing when you're trying to run on an implemention you haven't yet seen: how to do this is outwith the scope of this answer I think.
Solved it.
The quickloading of the custom package was taking me into the package. I did not realize that. So I had to specify split-sequence is from outside. So, I replaced all occurrences of split-sequence in the function definition with
LISPWORKS:split-sequence
Then it worked.
If any one has a better solution, please do let me know. Thanks

What Emacs Lisp function is to `require` as `autoload` is to `load`?

I am trying to program GNU Emacs 23 to issue require commands lazily, on demand, instead of up front in my .emacs file. If I wanted to delay the execution of a load command, I could use autoload. But require and load take different sorts of arguments.
Is there a predefined function that does for require the same job that autoload does for load? And if not, what tools would people recommend that I use to roll my own?
There is not difference between require and load with regards to autoload. require is just a frontend to load, which more or less comes down to:
(defun require (feature &optional filename noerror)
(unless (featurep feature)
(let ((filename (or filename (symbol-name feature))))
(load filename noerror))))
As you can see, the symbol name given to require is equal to the filename given to load. As a matter of fact, the first (require 'foo) evaluated in an Emacs session is equivalent to (load "foo").
Thus, you can just use (auto-load 'foo-function "foo") for foo-function from the library foo, that you can load with (require 'foo).
One more answer to help clarify (this was a little verbose for a comment):
autoload says "if this function isn't already defined, then load this file (if and when the function is called)."
require says "if this library isn't already loaded, then load this file (immediately)."
Note in particular that you don't need to use require to load a library; that's simply the way you ensure that you don't load it again (assuming you don't want to do that). The (provide 'FEATURE) expression in the library will be evaluated no matter how the library was loaded, which lets any future require know that it doesn't need to do anything.
It's a similar situation for autoload -- if the file has already been loaded (and therefore the function in question properly defined), then the autoload no longer has any effect.
What kind of "demand" do you have in mind for your "on demand"?
If a given command or other function needs (or soft-needs) a given library, then that function itself can use (require 'foo) or (require 'foo nil t). The library will be loaded on demand from that function.
Consider also whether you might need to load the file more than once, i.e., reload it in some situations, whether or not it has already been loaded.
For #2, for instance, my code that uses a library of Lisp macros, icicles-mac.el does not just use require, because I want to make sure that if a user gets a new version of that library (e.g., downloads a new source version and byte-compiles it) then that new version is used whenever s?he byte-compiles another library that needs it. (This is important -- when a library of macros changes, other libraries that use those macros generally need to be recompiled after loading the new macros file.) For that, instead of just (require 'icicles-mac) I use this:
(eval-when-compile
(or (condition-case nil
(load-library "icicles-mac") ; Use load-library to ensure latest .elc.
(error nil))
(require 'icicles-mac))) ; Require, so can load separately if not on `load-path'.

Controlling verbosity of byte-compilation (CL library)

When byte-compiling several eLisp files in a batch the output from the compiler is cluttered with Warning: function `position' from cl package called at runtime warnings. I understand, although don't agree that much with the policy on cl package. But this makes spotting other, more useful warnings more difficult. So, while there's no real way to avoid the warning, is there a way to selectively shut off all warnings of a certain pattern?
EDIT: (attached an example)
create file called doodles.el
(require 'cl)
(eval-when-compile (require 'cl))
(dotimes (i 1)
(position ?\x "x"))
M-x byte-compile-file RET doodles.el
Switch to *Compile-Log* buffer:
doodles.el:1:1:Warning: cl package required at runtime
this is what you get.
You can control byte-compiler warnings with a Local variables block that sets the byte-compile-warnings variable. To turn off the CL-at-runtime warning, place this near the end of your module:
;; Local Variables:
;; byte-compile-warnings: (not cl-functions)
;; End:
The warning function position from cl package called at runtime is not there because of the policy on CL (well, it does have something to do with it, admittedly) but is pointing out an actual real problem: you use position in a file which does not (require 'cl). The file probably does (eval-when-compile (require 'cl)) which means CL is available during compilation (a.g. to expand CL macros), but will not be loaded at run time.
Often this does not result in a bug, because some other file somewhere does (require 'cl) for you, but that's just you being lucky.

How to make and use library with lisp (clisp)?

In C/C++, I can make a library, and make it static one or dll using #include "" in source code, and -labc when linking.
How do I have the same feature in lisp?
As an example of util.lisp in directory A. I define a library function hello.
(defpackage "UTIL"
(:use "COMMON-LISP")
(:nicknames "UT")
(:export "HELLO"))
(in-package util)
(defun hello ()
(format t "hello, world"))
And try to use this library function from main function.
(defun main ()
(ut:hello))
(main)
I tried
clisp main.lisp A/util.lisp
But, I got the following message
*** - READ from #: there is no package with name "UT"
What's the equivalent of #include "" to use the library?
What's the equivalent of -lutil to load the library? What's the command line for clisp/sbcl to use the library?
And for defpackage, Is this equivalent to namespace?
ADDED
I just had to load the library.
(load "./A/util.lisp")
(defun main ()
(ut:hello))
(main)
And run 'clisp main.lisp' works fine.
What you are looking for are called systems. Common Lisp's defpackage has nothing to do with this, and yes, it's about namespaces. Have a look at the HyperSpec, or the idiot's guide (see Xach's comment below) to read more about it.
You can restrict yourself to merely loading files, but usually, a system definition facility is used; mostly ASDF nowadays. A minimal example:
(defsystem my-system
:name "my-system"
:version "0.0.1"
:author "myself"
:license "LLGPL"
:description "it's a system."
:serial t
:components ((:file "packages")
(:file "stuff")
(:file "more_stuff")))
Where packages.lisp would contain the package definition, stuff and more_stuff are the lisp or fasl files to be loaded. This system definition (usually named filename.asd) must be symlinked to (or located in) a directory contained in asdf:*central-registry* for ASDF to find your system. Then, you can load the system thusly:
(asdf:oos 'asdf:load-op 'my-system)
An alternative to this has been added in more recent versions of ASDF:
(asdf:load-system 'my-system)
Or, when using slime, by pressing ,l my-system RET.
You have to load util.lisp before main.lisp:
> (load "util.lisp")
> (load "main.lisp")
> (main)
hello, world
NIL
Practical Common Lisp has a good introduction to defining and using packages.
Common Lisp is an image base language, although usually to a lesser extent than Smalltalk. This means that you use a library by loading it into the image, using LOAD (if used explicitly the often in form (load (compile-file "your-file-here"))), or usually with a system definition facility like ASDF. The loaded code is then available for all code compiled/loaded in the future.
Packages are indeed namespaces. They deal with mapping strings to symbols only, they are not connected directly to files or functions or anything else. You received a package error because you attempted to load a file using a package before a file defining it.