At run time, you can inspect the current binding of f to see whether it is a macro, function or whatever. In an interpreter with fexprs, it would be late like this. At the time (f ...) is being called, if it was redefined to a fexpr, we go with that. If it is still a function, we call that.