[Top][All Lists]
[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'.