[plt-scheme] get the list of modules in a namespace

From: YC (yinso.chen at gmail.com)
Date: Fri Aug 1 03:03:18 EDT 2008

On Wed, Jul 30, 2008 at 6:57 PM, Eli Barzilay <eli at barzilay.org> wrote:

> Seems like there is only `namespace-module-registry', which returns a
> value that you can't really use for anything (see the docs).  But I
> think that to merge two namespaces you'll need to scan the bindings
> from each one and create the appropriate bindings in the result, and
> `identifier-binding' is what is needed for doing this.

Thanks Eli.

I got from identifier-binding to resolved-module-path, and was able to get
quite a bit to work, except the following issues:

   1. namespace-require does not work with built-in modules such as %network
   2. namespace-require also does not work with top-level modules such as
   3. top-level bindings requires a different approach

Lastly - it appears expensive to having to loop through all bindings...
hopefully something like namespace-module-registry can offer more in the
future? ;)

Below is what I've got in case anyone is interested...

;; retrieve the module binding by sym and namespace
(define (get-module-binding sym (ns (current-namespace)))
  (parameterize ((current-namespace ns))
    (identifier-binding (namespace-symbol->identifier sym))))

;; retrieve the module path (resolved) by sym and namespace
(define (get-module-path sym (ns (current-namespace)))
  (parameterize ((current-namespace ns))
    (let ((binding (get-module-binding sym ns)))
      (cond ((or (eq? binding #f) (equal? binding 'lexical))
               (car binding))))))))

;; filters duplicates in a list.
(define (list->unique-list lst)
  (define (helper rest acc)
    (cond ((null? rest) (reverse acc))
           (if (member (car rest) acc)
               (helper (cdr rest) acc)
               (helper (cdr rest) (cons (car rest) acc))))))
  (helper lst '()))

;; turn the symbols into module path and filter dupes.
(define (namespace->module-paths (ns (current-namespace)))
   (map (lambda (sym)
          (get-module-path sym ns))
        (namespace-mapped-symbols ns))))

;; compare two module paths and return the differences (one way)
(define (namespace-module-paths-diff from-ns to-ns)
  (let ((from-paths (namespace->module-paths from-ns))
        (to-paths (namespace->module-paths to-ns)))
    (filter (lambda (p)
              (not (member p to-paths)))

;; take the diffs in module paths and require them.
(define (namespace-merge from-ns to-ns)
  (let ((ns-paths (namespace-module-paths-diff from-ns to-ns)))
    (parameterize ((current-namespace to-ns))
      (for-each (lambda (path)
                  (when path
                    ;; doesn't work with #%network or top-level modules
                    (namespace-require path)))

;; examples...
(define ns (make-base-namespace))

;; current-namespace in top-level is scheme. will choke on #%network for
(namespace-merge (current-namespace) ns)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20080801/33772b9a/attachment.html>

Posted on the users mailing list.