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

Reply via email to