Four modules:
- Defines library functions
- Defines library macros that use library functions
- Defines application functions that use library macros
- Loads the other three
libfunc.scm:
(define (my-func ls) ...)
libmacro.scm:
(define-macro (my-macro ls) (define mfls (my-func ls)) `...
libapp.scm
(define app (begin (my-macro '(1 2 3 ...
libmain.scm
(load "libfunc.scm")
(load "libmacro.scm")
(load "libapp.scm")
(define (main . args) (app ...
Porting from another scheme where this works to Gambit-C where it doesn't. I'm starting to think it's impossible. Gambit-C has ##define-macro
and ##namespace
which might be relevant but are documented nowhere and un-googlable. One thing I did find in Meroon, which is a big library portable across many Schemes, is this code for working around Gambit-C.
Edit: I think Christian Queinnec, Meroon's author, had a good handle on the issues. He wrote 23 things I know about modules for Scheme. I feel like if I spoke both French and Scheme that it would give me all the answers.
Edit 2: I took a look at the original Scheme which was pretty-much purpose built to run the system I'm trying to port. It turns out they cheat. Every "function" that is called from a define-macro
has a shadow-implementation in C that is attached to the macro-global namespace. That might be a trick I can copy in Gambit-C since it is very C oriented but I'm still researching that possibility.
I don't know if it's possible to call normally define
d functions from a macro using syntax case. I can't find anything easy-to-understand about it (most documentation seems to be written by and for phds) but there's a very interesting tutorial on define-syntax
and syntax-case
which shows that you can implement any function as a macro. It even implements a basic Lisp in macros. So that's something. JRM's Syntax-rules Primer for the Merely Eccentric
Edit 3: Like @GoZoner says this can be done using for-syntax
and define-syntax
, at least in Racket. Remains to be seen if it can work in Gambit-C
#lang racket
(require srfi/1)
(require (for-syntax srfi/1))
(require (for-syntax syntax/stx))
(define-syntax (fnodup x)
(define mydat (delete-duplicates (syntax->datum x)))
(syntax-case mydat ()
[(fnodup f) #'(f) ]
[(fnodup f x0) #'(f x0) ]
[(fnodup f x0 ...) #'(f '(x0 ...)) ]
))
(fnodup print "hi" "der" "hi")
(require (for-syntax ...
is where the magic happens. Racket has it. Gambit-C doesn't.
When 'new to Scheme', stick to Scheme. The syntactic form 'define-macro' is not part of any Scheme standard and is, from the example you've given, a highly inferior macro system compared to what is in the Scheme standard.
Look at R5RS, R6RS or R7RS to understand
syntax-rules
as your step #1. After thatsyntax-case
in R6RS lets you do other stuff.