Closed vuolen closed 4 years ago
Compiling a macro that calls itself as part of its definition like that would always recurse infinitely: To compile the function that implements the macro test
, the compiler would need to know what code (test)
returns, so it would need to call the macro test
to find out, so it would need to compile the function that implements the macro test
, et cetera, recurring infinitely. This is why I made macros only be in scope strictly after their definition.
What you can do instead is have the macro return code that calls it:
(macro test
(lambda (x)
; If we got an argument, return it.
; If we got NO argument, return a call to this macro, with a default.
(if x (return x)
(return '(test defaultArgument)))))
(test)
(test notTheDefault)
Output JS:
defaultArgument;
notTheDefault;
It works because the macro isn't called in its definition, but it instead returns code that calls it.
Or if the macro requires fancier recursive computation on its arguments, it might be easier to just define a recursive function inside the macro definition (like factorial
here), and call that:
(macro !
(lambda (thing)
(var factorial
(lambda (x)
(if (== x 1)
(return x)
(return (* x (factorial (- x 1)))))))
(return ((. this atom) (factorial ((. this evaluate) thing))))))
(! 5)
(! (+ 3 2))
Output JS:
120;
120;
Does that answer your question?
Apologies for my simplified example. Of course it would cause an infinite loop if it worked, my intention was to just recreate the error message.
However, you managed to answer the actual question in hand. Thank you!
I might be missing something, but a simple recursive macro call
leads to the error
Calling
arguments.callee
works, however it is neither recommended or elegant. Is there any alternative?