I'm sorry, I don't really understand what you're getting at when you say that I'm confusing "how macros are used" and "what macros are". Perhaps we're just disagreeing about terminology?
What I mean by a "macro" is: a convenient way to extend the syntax of a particular syntax class by telling my language how to translate the syntactic construct I want to add into constructs it already understands. In this sense one definitely can have expression-macros and pattern-macros. Is there some reason you think one shouldn't have this in a language?
Your new proposed `if-match' is strange. I'm not sure how I'd use it to, for example, implement a "list" pattern-macro, such that `(list p1 p2 p3)' matches any list of three elements, whose first element matches p1, second matches p2, and third matches p3. You seem to intend that `((list p1 p2 p3) expr then else)` should macro-expand to the code that performs this pattern match. This is difficult for two reasons:
1. I'd need to shadow the definition of `list' with a macro that usually behaves like the list function, but if used inside of if-match behaves differently. This seems difficult, and is conceptually ugly.
2. AIUI, to get `((list p1 p2 p3) expr then else)' to macro-expand specially, `(list p1 p2 p3)' has to macro-expand to a symbol naming a macro, call it MAGIC, such that `(MAGIC expr then else)` expands to the desired result. This is difficult, because MAGIC needs to know about p1, p2, and p3. So `(list p1 p2 p3)' will need to dynamically define a new macro (with a gensym'ed name) that knows specifically about p1, p2, and p3, and return that. This may be possible, but is gnarly as fuck.
This is certainly very far from being "the obvious way to do it" to anyone but a wizard.
Maybe I'm misunderstanding you, or you made a typo?
My definition of macro would be: a function that's evaluated at compile time.
In this sense, the idea of an "expression-macro" and a "pattern-macro" makes as much sense as an "expression-function" or "pattern-function". We don't typically have different classes of function to fulfil different purposes.
The `if-match` macro you describe could be written as a function, albeit with less pleasing syntax:
So in the above case, we allow literal values to be passed in, or a function which returns a map of symbols to matching values. It's the function that allows for the extensibility.
A macro can easily smooth over the janky syntax of the `then` and `else` functions, and we'd end up something like this:
(if-match (pattern/cons 0 x)
'(0 hi there)
x
nil)
This is essentially what my previous example was alluding to, though in that I intended to use a namespaced macro rather than a namespaced function for extensibility.
You might well complain that `(pattern/cons 0 x)` is more verbose than `(cons 0 x)`, but it's also unambiguous, and doesn't require what would amount to a separate namespacing system, which a Lisp-1 like Clojure tends to reject.
Now, I don't think the above examples are magical in any way. The macro is a small improvement over the function, and the function isn't particularly complex. If higher-order functions are your idea of wizardry, then there's not much in Lisp that you wouldn't consider magic.
Maybe your objection just stems from the use of something like `p/cons` instead of just `cons`, while still desiring `cons` to be namespaced in some way. In which case, I'd suggest that what you're really asking is not 'can I have expression-macros and pattern-macros', but 'can I create new namespacing systems'.
What I mean by a "macro" is: a convenient way to extend the syntax of a particular syntax class by telling my language how to translate the syntactic construct I want to add into constructs it already understands. In this sense one definitely can have expression-macros and pattern-macros. Is there some reason you think one shouldn't have this in a language?
Your new proposed `if-match' is strange. I'm not sure how I'd use it to, for example, implement a "list" pattern-macro, such that `(list p1 p2 p3)' matches any list of three elements, whose first element matches p1, second matches p2, and third matches p3. You seem to intend that `((list p1 p2 p3) expr then else)` should macro-expand to the code that performs this pattern match. This is difficult for two reasons:
1. I'd need to shadow the definition of `list' with a macro that usually behaves like the list function, but if used inside of if-match behaves differently. This seems difficult, and is conceptually ugly.
2. AIUI, to get `((list p1 p2 p3) expr then else)' to macro-expand specially, `(list p1 p2 p3)' has to macro-expand to a symbol naming a macro, call it MAGIC, such that `(MAGIC expr then else)` expands to the desired result. This is difficult, because MAGIC needs to know about p1, p2, and p3. So `(list p1 p2 p3)' will need to dynamically define a new macro (with a gensym'ed name) that knows specifically about p1, p2, and p3, and return that. This may be possible, but is gnarly as fuck.
This is certainly very far from being "the obvious way to do it" to anyone but a wizard.
Maybe I'm misunderstanding you, or you made a typo?