Package Tips
<-Previous | ^UP^ | Next->
When to use packages
- If you are starting a new application or project
- If you find yourself copying and pasting from another project/application (create a new package that would be shared between the 2 projects/applications, put the code in that new package and export the symbol
- If you are writing some general purpose functions which you intend to share
Some package guidelines
When working with packages theres a few things you need to know to make it all work smoothly
- Packages must be defined before you can Load or Compile a file containing an in-package statement refering to that package
This means there is an order in which files must be loaded, in turn implying that the code defining a package should be in a separate file to code that uses those packages. We'll get onto both of these topics later
- Packages must be defined before other packages can refer to them
Practically this means avoiding circularities in the :use statement, but again implies form form of load order which again means keeping code defining packages in separate files
- Code files should contain one, and only one, in-package statement and this should be the first line of code in that file
As far as Common Lisp is concerned you can put multiple in-package statements in a file. There are however 2 reasons why this approach would be considered good practice
- It avoids confusing humand who might not notice a second or third in-package statement
- The emacs/SLIME development environment look for the in-package statement to determine the package to be used when communicationg with Common Lisp and multiple in-package statement may confuse these tools
- A final consideration is naming of Packages and particularly avoiding package name clashes.
This isn't generally a problem when you are only using packages that you have developed, but if you are sharing them with other programmers, or using third party packages this needs to be considered, with some kind of naming convention. As a package name is just a text string you can adopt any convention you choose. A trend seems to be a reverse internet domain name followed by a description, for example com.genworks.my-app
Some package gotcha's
Generally once you've got working with packages you won't need to think about them that much, they just do what they're supposed to do. But occasionally, and mainly when setting up new packages, there can be a few 'odd' errors. Perhaps the most common is symbol conflicts. Consider the following case
- You create a package, say my-package, which you expect to use a function, say test-function, which is :exported from another package my-functions
- In the source code for the app using my-package, you refer to test-function by its symbol only - which is fine because its exported
- But you've forgotten to :use my-functions when defining the package my-package So when you try to run the compiled code, you'll get an 'undefined function' error. No problem, you return to the define-package statement for my-package, add (:use my-functions) and then try to run again. This time you get a conflicting symbols error! Whats happened here is that the first time you run the code the the symbol test-function is interned in my-package. Then you :use my-functions from which test-function is exported so you've got a conflicting symbol clash! The solution is to accept the restart to unintern test-function from my-package and then recompile the my-package package
Another issue potential issue is
- You create a package, say my-package, which :uses my-functions
- my-functions :exports a number of functions
- You then define a function in my-package which has the same symbol as a function :exported from my-functions
A final package-related issue is to do with dropping out of Geysr into the REPL to do some debugging. If the debugging is referring to slots defined in a package other than the REPL's current package, when you try to evaluate the slot you'll get an 'undefined function' error. The simple solution to this is to change the REPL's package, using the in-package function, to the package of the code that you're working with and evaluate the expression again