I've been working through Practical Common Lisp's binary parser project, and attempted to split the generics (class and macro definitions) and specifics (specific types and method implementations) into different packages. As such, I have the following code:
In packages.lisp:
(defpackage :binparse
(:use :cl)
(:export :read-value :write-value :read-object :write-object
:current-binary-object :parent-of-type :define-binary-class
:define-tagged-binary-class :define-binary-type))
(defpackage :primitives
(:use :cl :binparse))
In binparse.lisp:
(defgeneric read-value (type stream &key)
(:documentation "Read a value of the given type from the stream."))
(defgeneric write-value (type stream value &key)
(:documentation "Write the value of the given type to the stream."))
(defmacro define-binary-type (name (&rest args) &body spec) ...) ; calls defmethod for read-value and write-value, specialized on (type (eql ,name))
In primitives.lisp:
(define-binary-type u1 () ...) ; defines reader and writer spec for 1-byte unsigned int, specialized on (type (eql 'u1))
I have been unable to determine how to properly export the method implementations from primitives
. If I don't do any exports beyond what's defined in packages
above, then I can do the following:
CL-USER> (binparse:read-value primitives::'u1 *testfile*) ; succeeds
CL-USER> (binparse:read-value primitives::u1 *testfile*) ; fails, unbound variable U1
CL-USER> (binparse:read-value 'u1 *testfile*); fails, class-not-found u1
PRIMITIVES> (read-value 'u1 *testfile*) ; succeeds
However, I can't figure out how to export 'u1
(or other symbols used as method specifiers) from primitives
to avoid the double-colon or potentially allow importing into other packages. Including (:export :u1)
in the defpackage
doesn't work. Nor does calling (export 'u1)
while already in primitives
. And single-colon, unlike double-colon, doesn't allow the ::'u1
that worked originally.
This seems like a fairly normal thing to want to do to expand on the project from PCL, defining the basic binary-parser code in a package to be used elsewhere for specific extensions, but I can't figure out how to do it and haven't found anyone else asking about it.
Figured it out: If I (:export #:u1)
in packages.lisp
, I can get the correct specialization of the method using (binparse:read-value 'primitives:u1 *testfile*)
. So, the quote goes before the package-name part of the symbol.