Search code examples
macrosschemelispkawa

Scheme (Kawa) - How to force macro expansion inside another macro


I want to make a macro, that when used in class definition creates a field, it's public setter, and an annotation. However, it'd seem the macro is not expanding, mostly because it's used inside other (class definition) macro.

Here is an example how to define a class with one field:

(define-simple-class test-class ()
    (foo :: java.util.List ))

My macro (only defines field as of now):

(define-syntax autowire
  (syntax-rules ()
    ((autowire class id) 
            (id :: class))))

However, if I try to use it:

(define-simple-class test-class ()
    (autowire java.util.List foo))

and query fields of the new class via reflection, I can see that it creates a field named autowire, and foo is nowhere to be seen. Looks like an issue of the order the macros are expanded.


Solution

  • Yes, macros are expanded “from the outside in”. After expanding define-simple-class, the subform (autowire java.util.List foo) does not exist anymore.

    If you want this kind of behaviour modification, you need to define your own define-not-so-simple-class macro, which might expand to a define-simple-class form.

    However, please step back before making such a minor tweak to something that is standard, and ask yourself whether it is worth it. The upside might be syntax that is slightly better aligned to the way you think, but the downside is that it might be worse aligned to the way others think (who might need to understand your code). There is a maxim for maintainable and readable coding: “be conventional”.