guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: rfc: `process-define-module': function -> macro ?


From: Marius Vollmer
Subject: Re: rfc: `process-define-module': function -> macro ?
Date: 21 May 2001 03:00:50 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.0.102

thi <address@hidden> writes:

> i've just been investigating how to clean up `resolve-interface' so that
> it's not necessary to do `eval'.

As a clarification, I wanted to avoid `eval' not because it is somehow
`evil', but because `resolve-interface' had a unusual calling
convention that wasn't really useful for general use.  Suppose someone
wanted to use it like this:

    (define (crazy-module-mender id)
      (define (renamer sym)
        (symbol-append id '- sym))
      (let ((interface (resolve-interface '((blib blub) :renamer renamer))))
         ...))

This wouldn't work since `renamer' is not on top-level.

I would find it more natural to make `resolve-interface' take keyword
arguments (as provided by (ice-9 optargs)) so that it can be used like
this:

    (define (crazy-module-mender id)
      (define (renamer sym)
        (symbol-append id '- sym))
      (let ((interface (resolve-interface '(blib blub) :renamer renamer)))
         ...))

In effect, a keywordized version of your `%resolve-interface', below.

This will leave the hard work of figuring out the syntax of a
interface spec to `use-modules' and `define-module'.  How they
partition their work between themselves and the `process-' helper
functions is up to them.

For example, we could have a helper function

    (define (interface-spec spec)
      (define (make-keyarg sym key quote?)
        (cond ((or (memq sym spec)
                   (memq key spec))
               => (lambda (rest)
                    (if quote?
                        (list key (list 'quote (cadr rest)))
                        (list key (cadr rest)))))
              (else
               '())))
      (define keys 
        ;; sym     key      quote?
        '((:select #:select #t)
          (:rename #:rename #f)))
      (define (map-apply func list)
        (map (lambda (args) (apply func args)) list))
      (if (not (pair? (car spec)))
          `(resolve-interface ',spec)
          `(resolve-interface ',(car spec)
                              ,@(apply append (map-apply make-keyarg keys)))))
      

that expands a SPEC into code for computing the args to
resolve-interface.

    (interface-spec->args '((blib blub) :select (a b) :rename prefixer)) 
    =>
    ((quote (blib blub)) #:select (quote (a b)) #:rename prefixer)

`use-module' could use this like this

    (define (process-use-modules module-interface-args)
      (for-each (lambda (mif-args)
                  (let ((mod-iface (apply resolve-interface mif-args)))
                    (or mod-iface
                        (error "no such module" mif-spec))
                    (module-use! (current-module) mod-iface)))
                module-interface-args))

    (defmacro use-modules modules
      `(eval-case
        ((load-toplevel)
         (process-use-modules-1
          (list ,@(map (lambda (m)
                         `(list ,@(interface-spec->args m)))
                       modules))))
        (else
         (error "use-modules can only be used at the top level"))))

A similar setup can be used for `define-module' and `process-define-module'.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]