Closed ChengCat closed 5 years ago
Another idea is (attr notype)
. notype
macros won't be evaluated only to determine its return type, and the situation of multiple evaluation of notype
macros is similar to that of traditional LIsp languages.
ChangCat: I think you are right, that evaluating the expressions of macros is in most cases not a good idea, because in most cases, you would just want to use macros without ever directly evaluating the forms, like let does.
Scopes for example will have two different kinds of macros: One, that works on the S-Expressions directly, like traditional lisp, and one that works on a typed AST. Like there I would prefer two different kinds of macros, one just syntax and one with type information. Maybe the one with type information could even be implemented on top of the one without, by manually evaluating the yet untyped forms and calling typed version then.
(attr notype)
seems like the best simple solution for now, and would also do the same as two different macro kinds.
@porky11 I know of Scopes, and feel that its approach with two different syntax tree is weird, i.e. one is the written sexp, and the other is the underlying semantics. In traditional Lisps and Dale, there is only one kind of syntax tree. Having two different kinds of syntax tree seems to be an unwanted complication. I have tried to reach its author along with some other concerns, but unfortunately haven't got any reply yet.
I think Dale's approach is fine. It's already not perfectly safe to do side effects in a macro in traditional Lisp languages, and Dale's type-of
-related mechanisms just opens up more possibilities for a macro to be evaluated multiple times. This breaks an assumption we implicitly hold when writing Lisp programs, but it is mostly fine when the macro is without any side effects. I think providing a mechanism for safe macro side-effects would be nice. To be honest, I am not entirely satisfied with my suggestions, I hope someone can come up with something better.
Another idea is that, we forbid overloading the same symbol with both functions and macros, when we can't determine only by the number of arguments whether it's function or macro to dispatch. This way, operator-macros will still work, and an entire class of multiple evaluation of macros is eliminated.
This idea can be combined with (attr notype)
, to get a behaviour similar to that of traditional Lisp.
That also was my idea, that (attr notype)
would disallow defining macros with the same types.
Closing this issue, since we now have a better idea in #201 to enable safe macro side effects, without any attribute annotation.
In general, a macro may be evaluated more than once, for the following cases:
type-of
eval-expression
eval-macro-call
Therefore it's not safe in general for macros to have side effects. On the other hand, macro side-effects are useful, so I suggest that we introduce a new attribute
(attr once)
, for those macros which do have side-effects to be safely written. This attribute will guarantee the macro is evaluated at most once, by prohibiting evaluation in all the above listed cases.It's still possible for one appearance of macro in source code to be evaluated more than once: