Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

: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?


2 Answers

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.

like image 145
Renzo Avatar answered Jan 02 '26 00:01

Renzo


Check the difference without changing the current package. You will find more information e.g. here

like image 45
Martin Buchmann Avatar answered Jan 02 '26 01:01

Martin Buchmann