[Openmcl-devel] with-package

Pascal J. Bourguignon pjb at informatimago.com
Mon Jan 14 12:52:21 PST 2013

Taoufik Dachraoui <dachraoui.taoufik at gmail.com> writes:

> This implementation is just the start to see check the concept and if
> it is useful; it is not robust and do not deal with
> exceptional situations (like use/unuse ccl)
> I will modify the code such that when you use ccl or common-lisp-user
> it does nothing (those packages are used in all new packages)
> But I understand your test and when use a package other than ccl or
> common-lisp-user it works fine:
> ? (with-package (calculus)
>            (let ((#1=#:hello 'world))
>              (print (list #1# #1#))))
> why you say the code contains a lot of non-conforming code? 

DEFPACKAGE without a :USE clause is not conforming: the default use list
depends on the implementation.

Using "CCL" is not conforming: this is an implementation package, it
won't be present in other implementations.

You could wrap this function (ccl::current-directory-name) in your own

    (defun getcwd ()
       #+ccl (ccl::current-directory-name)
       #-ccl (error "Please implement getcwd on ~A"

> but
> anyway, this can be corrected once
> i know what is conforming and what is not

Yes.  That's the spirit!

> what is important at this point is to see if the concept is working
> and if it is useful, anything else can be corrected

Conceptually, there is this problem that you're masking the symbols from
the used packages that have the same name as symbols exported from
package indicated in the with-package form.

(defpackage :p1 
  (:use :cl :mb))

(defun f ()

(defpackage :p2
  (:use :cl)
  (:export :f))

(defun p2::f ()

(in-package :p1)

(with-package (:p2)
;; --> "p2::f"

;; and even worse:
(with-package (:p2)
;; --> "p2::f" ; !!!

Conceptually, there's this other problem that you're making the packages
for the files, with a fixed use list.  This is silly, since each file
will usually want to use a different set of packages.

Once the package is created (however, in your case by make-package), it
cannot be redefined with a DEFPACKAGE form in the file.  So you can only
modify the package with package modification functions.  In general it's
not a good idea, because then there are strong dependencies between the
files, that are established only at load time.  For you of course it
doesn't matter, since you have only one file per package.  But this will
be a concern when you realize that you need more than one file to
implement a given package.  (Some may be big).

> I do not understand the following:
> "FILE-WRITE-DATE could return nil while the file is still loadable.
> If you don't want to modify the package if the file can't be openned,
> you can open it with WITH-OPEN-FILE, and pass the file-stream to
> LOAD."

    (defun %make-package (file nickname)
      (with-open-file (stream file)
        (let ((*package* (or (find-package nickname)
                             (make-package (namestring file)
                                           :use '("COMMON-LISP" "MB"
                                                  #+ccl "CCL")
                                           :nicknames `(,nickname)))))
          (%new-symbol "**MB-PACKAGE-TIMESTAMP**" *package* (file-write-date stream))
          (%new-symbol "**MB-IMPORTED-SYMBOLS**" *package* (make-hash-table :test 'equal))
          (load stream))))

__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.

More information about the Openmcl-devel mailing list