Hi Mike, Mike Gran <spk...@yahoo.com> writes:
> Hey all, > > I need help making a macro. > > I have an existing procedure of the form > > (call-method self method (...)) > > Note that SELF is a struct, METHOD is a string, and the ellipses can > be anything. > > I would like to make a macro that transforms into the above, but, is > of the form > > (send self (method ...)) > > where SELF is the same struct, METHOD is a literal symbol, and the > ellipses are unchanged. > > For example, I would like to call > > (send date (get-year)) > (send date (set-year 2018)) > (send date (set-dmy 1 1 2018)) > > and have it be > > (call-method date "get-year" '()) > (call-method date "set-year" (list 2018)) > (call-method date "set-dmy" (list 1 1 2018)) > > I get hung up on figuring out how to handle the literal symbol and the > ellipses. Here's a syntax-rules macro to do it: (define-syntax send (syntax-rules () ((send self (method arg ...)) (call-method self (symbol->string 'method) `(,arg ...))))) However, in this implementation, the 'symbol->string' call is deferred to run time. Here's a syntax-case macro that does the conversion at compile time: (define-syntax send (lambda (stx) (syntax-case stx () ((send self (method arg ...)) (identifier? #'method) (with-syntax ((method-str (symbol->string (syntax->datum #'method)))) #'(call-method self method-str `(,arg ...))))))) This syntax-case macro also verifies at compile time that 'method' is a bare identifier, via the guard (identifier? #'method). Note that to generate the list of arguments, the simpler approach would have been to write (list arg ...) instead of `(,arg ...). I chose to use quasiquote mainly to benefit from an optimization in the quasiquote macro, namely that `() expands into '(), which is preferable to (list). Mark