davypough
davypough

Reputation: 1941

Package Shadowing for Multiple Packages and Symbols - how to use cl21

Loading the Quicklisp system :cl21 (Common Lisp for the 21st Century) produces many conflicts with the :cl package. (But this is by design.) Is there a convenient way to specify that any conflicts should be resolved in favor of :cl21? The following definition resolves conflicts individually, but is tedious, since there are hundreds of symbols needing shadowing:

(defpackage :my-pkg
  (:use :cl :cl21)
  (:shadowing-import-from :cl21.core.hash-table :hash-table-count)
  (:shadowing-import-from :cl21.core.sequence :position :substitute-if)
  (:shadowing-import-from :cl21.core.package :rename-package :use-package)
  (:shadowing-import-from :closer-mop :standard-generic-function)
  ...)

The solution I have so far is to write a macro called defpackage* that expands into a defpackage like that above:

(defun package-externals (pkg-name)
  "Returns the external symbols in a named package."
  (let (pkg-syms)
    (do-external-symbols (sym (find-package pkg-name) pkg-syms)
      (push (list pkg-name sym) pkg-syms))))

(defmacro defpackage* (pkg-name use-list shadow-pkg-names)
  "Adds shadowing imports from a list of package names."
  (let ((shadow-externals (loop for pkg in shadow-pkg-names
                            append (package-externals pkg))))
    `(defpackage ,pkg-name ,use-list
       ,@(loop for ext in shadow-externals
            collect `(:shadowing-import-from ,@ext)))))

The third argument shadow-pkg-names is the list of package names from which the exported symbols will be extracted. For example, a macro call might look like:

(defpackage* :my-pkg
  (:use :cl :cl21)
  (:cl21.core.hash-table :cl21.core.sequence :cl21.core.package ...))

However, I'm not sure how to get the complete list of packages to insert in the macro from a Quicklisp system like :cl21. (A manual count of the :cl21 packages comes in at 30, with varying numbers of exported symbols from each package.)

At a more general level, is this the simplest way to resolve conflicts en masse? Note that there is another post at Use package shadowing symbols which deals with a similar issue, but I'm finding it hard to follow (except perhaps for the idea of using a reader macro to splice in the long list of :shadowing-import-from clauses). Also note that loading :cl21 does not seem straightforward, as I've had to start from scratch every time with (but don't know why):

(let ((quicklisp-init (merge-pathnames "quicklisp\\setup.lisp" (user-homedir-pathname))))
  (when (probe-file quicklisp-init)
    (load quicklisp-init)))

(ql-dist:install-dist "http://dists.cl21.org/cl21.txt")

(ql:quickload :cl21)

Upvotes: 0

Views: 230

Answers (1)

Svante
Svante

Reputation: 51531

Don't use both cl and cl21. Just use cl21 if you want that.

Cl21 both exports symbols for functionality it changed with respect to cl and re-exports any unchanged symbols. It is designed as something like a replacement “base” package.

Upvotes: 3

Related Questions