Julia: Deprecate `macro`

Created on 12 Jun 2020  路  3Comments  路  Source: JuliaLang/julia

I propose to deprecate macro both as a construct and as a concept.

I came to this idea from the fact that whenever I write a macro that macro often does nothing more than call a function which does the actual code transformation. That way it's much easier to debug, and if I need to use the transformation in a non-macro setting I can easily do so.

My suggestion is simple:

  1. There are no macros, just normal functions that transform Exprs
  2. The @somefunction(someexpr) syntax will transform that someexpr in exactly the way it does now.

The conceptual change is going away from the idea of a macro as an entity, and moving all the work it does into the special semantics of the calling of that function (to do the code substitution).

I would imagine that this isn't much of a change in implementation to what is going on now, but I think it brings some conceptual clarity and some practical benefits:

  • As I said above, we would mean we wouldn't have arbitrary decisions about what goes in a macro and what goes in a function
  • If I or someone else writes code-transformation that I want to use I can do so more easily if its in function form that if its in macroform
  • It's easier to understand. We don't need to teach newcomers that macros are just functions that transform expressions, because they would obviously be functions that just transform expressions

My guess is that we got to the current situation by a quirk. We adopted define-macro from scheme but did not adopt scheme's behaviour of having no special syntax for applying macros. Put differently, scheme could not get rid of define-macro because it has no syntax to make the differentiation that macro substitution happens at a different stage of compilation/interpretation.

I'm of course open to the possibility that there is some glaring problem with this proposal that I haven't seen. On slack @oxinabox noted that one problem could be that in current code there is a lot of overlap between function names and macro names, This is true, but I think a relatively small problem. Besides, we have multiple dispatch we could in most cases just specialise.

Deprecating macros would be a breaking change of course. One non-breaking change would be the ability to call code transforming functions as using some variant of the @ syntax

design macros speculative

Most helpful comment

This makes sense in that macros are already just functions (whose names begin with @). One obstacle is that we add extra arguments __source__ and __module__ to macros; I suppose you'd have to add them manually if we defined macros with the function keyword. I also think it can be useful to have both macro and function versions of the same name, e.g. @printf requiring a static format string vs. printf where everything is at run time. That seems more useful to me than having printf return the macro expansion of @printf, which is mostly useful for debugging and can already be done in other ways. So I think I'm mostly opposed to this.

All 3 comments

That way it's much easier to debug, and if I need to use the transformation in a non-macro setting I can easily do so.

You can call a macro directly and that's easy with var string macro

As I said above, we would mean we wouldn't have arbitrary decisions about what goes in a macro and what goes in a function

There's nothing arbitrary here. Nothing more arbitrary then when you want to call one function from another function.

It's easier to understand. We don't need to teach newcomers that macros are just functions that transform expressions, because they would obviously be functions that just transform expressions

This is really the easiest aspect of a macro and macro really aren't "just functions that transform expressions". There are a LOT more to macros than this, like handling the scope and such. In fact, I can't think of a single case where you want something to be both a macro and a normal function. The fact that macros are almost impossible to nest correctly without breaking hygene right now is a regression and a separate problem that needs to be fixed. When you define a macro, it is how people should use it and it shouldn't be any difference whether it's used by a user or someone that wants to wrap your macro. Calling the macro body directly without going through the macro expander first completely disgards all scope information and whenever you are doing it for macros someone else defined it is almost always wrong.

This makes sense in that macros are already just functions (whose names begin with @). One obstacle is that we add extra arguments __source__ and __module__ to macros; I suppose you'd have to add them manually if we defined macros with the function keyword. I also think it can be useful to have both macro and function versions of the same name, e.g. @printf requiring a static format string vs. printf where everything is at run time. That seems more useful to me than having printf return the macro expansion of @printf, which is mostly useful for debugging and can already be done in other ways. So I think I'm mostly opposed to this.

This makes sense in that macros are already just functions (whose names begin with @)

I think it actually makes even more sense than only that, since

julia> x = 3; @Base.show x;
x = 3
Was this page helpful?
0 / 5 - 0 ratings

Related issues

manor picture manor  路  3Comments

felixrehren picture felixrehren  路  3Comments

Keno picture Keno  路  3Comments

tkoolen picture tkoolen  路  3Comments

m-j-w picture m-j-w  路  3Comments