Packages

Packages are namespaces for symbols, not modules of code. A symbol belongs to one home package; :export makes it external; :use makes another package's external symbols accessible unqualified.

Use uninterned symbols (#:name) or keywords in defpackage to avoid interning symbols in the current package. UIOP's define-package adds conveniences (:mix, :reexport, :recycle).

;;;; package.lisp
(defpackage #:inventory
  (:use #:cl)                              ; inherit COMMON-LISP's external symbols
  (:import-from #:alexandria #:when-let #:hash-table-keys)
  (:local-nicknames (#:a #:alexandria))    ; package-local nicknames (widely supported)
  (:shadow #:remove)                       ; define our own REMOVE instead of CL:REMOVE
  (:export #:make-item #:item-name #:add-item #:remove #:total-value))

;;;; inventory.lisp
(in-package #:inventory)

(defstruct item name (price 0) (qty 0))
(defvar *items* (make-hash-table :test 'equal))
(defun add-item (item) (setf (gethash (item-name item) *items*) item))
(defun remove (name) (remhash name *items*))
(defun total-value ()
  (loop for item being the hash-values of *items*
        sum (* (item-price item) (item-qty item))))
(defun %internal-helper () :not-exported)  ; internal symbol
;; Using it
(inventory:add-item (inventory:make-item :name "pen" :price 2 :qty 10))
(inventory:total-value)                    ; 20
(inventory::%internal-helper)              ; :: accesses internal symbols (avoid in real code)
(in-package #:cl-user)
(do-external-symbols (s :inventory) (print s))
(find-package :inventory)
(package-name *package*)                   ; current package