In the following example, a syntax error is raised because of (apply op args) can't work when op is a macro like and.
How can I force the macro to go through the second branch when apply doesn't apply?
It’s possible to create something like my-and which is still a macro, but can be used as an identifier macro (and therefore would work with apply). I guess you want stuff like my-and to go through the first branch?
That's why I want to push cases where I can't apply to the second branch —
but I guess the "Can I use apply?" is a proxy for "is it safe to evaluate the inner expressions before the outer one?".
Your revision helped me realize this more clearly.
I still think we should be able to do better than syntax-local-value here.
In particular, when writing (= and 3), DrRacket complains with a syntax error and: bad syntax in: and, which means that it is possible to determine that and cannot be in non-application position at compile time, supposedly without evaluating it.
Yeah, that's pretty good, but I'm hoping to avoid the syntax-local-eval (which is kind of worse than syntax-local-value in sorawee's answer). It seems to me that a simpler check should be possible — but I'm not sure what.
I think syntax-local-value will work, but it may be more conservative than you would like: for example, it would put anything with the keyword-procedure optimization in the has-a-transformer-binding case.
You might want to local-expand the expression and look for #%plain-app (or maybe you also want to recognize #%app specially, or maybe add #%expression somewhere, or …).