[racket] Require macros
On 01/11/2011 09:08 AM, Eduardo Bellani wrote:
> Hello list.
>
> I am having a bit of a pain with trying to create a custom require
> syntax. I am trying to save some typing in an MVC like application by
> building some macros to recognize in the test files where the files to
> be tested are.
>
> I have 2 doubts I think, one is how to retrieve the module name for the
> my-model-test macro and the other is how to make those macros work in
> in the require form as the target-test.rkt file tries to do.
>
> BTW, I have looked at the require Macros section of the docs, but so far
> to no avail.
>
> For illustration, here is my (broken) code:
>
> ;; auxiliary.rkt
> #lang racket
>
> (require rackunit
> racket/require-syntax
> rackunit/text-ui)
>
> (provide (all-from-out rackunit)
> (all-from-out rackunit/text-ui)
> models-test
> my-model-test)
>
> (define-syntax my-model-test
> (syntax-rules ()
> [(_)
> (string-append "../app/model/" *MODULE-NAME*)]))
>
>
> (define-syntax models-test
> (syntax-rules ()
> [(_ model-name ...)
> (values (string-append "../app/model/" model-name) ...)]))
>
>
>
>
> ;;target-test.rkt
> (require "../auxiliary.rkt"
> (model-test "a-model")
> (my-model-test))
>
>
> Any ideas?
First, you need to use define-require-syntax:
(define-require-syntax from-model ___)
Next, since you want to compute the new path at compile time, you can't
use syntax-rules. If you do, then you'll return the string-append
expression as if it were a require form; but it isn't, and you'll get an
error.
(define-require-syntax (from-model stx)
(syntax-case stx ()
[(from-model relpath)
(string? (syntax-e #'relpath)) ;; only relative path, ie strings
___]))
Finally, you want to append the given string to a common prefix:
(string-append "../app/model/" (syntax-e #'relpath))
But that's a string, and your require macro must return a syntax object.
And since require is essentially a non-hygienic binding form that binds
names based on the lexical context of the require subforms, you get the
lexical context right. The right lexical context in this case is the
same as the original require form, stx:
(datum->syntax stx
(string-append "../app/model/" (syntax-e #'relpath)))
Then use it thus:
(require (from-model "some-file.rkt")
(from-model "another-file.rkt"))
Ryan