I'm learning Clojure macros, and wonder why we can't use just functions for metaprogramming.
As far as I know the difference between macro and function is that arguments of macro are not evaluated but passed as data structures and symbols as they are, whereas the return value is evaluated (in the place where macro is called). Macro works as a proxy between reader and evaluator, transforming the form in an arbitrary way before the evaluation takes place. Internally they may use all the language features, including functions, special forms, literals, recursion, other macros etc.
Functions are the opposite. Arguments are evaluated before the call, return value is not after return. But the mirroring nature of macros and functions makes me wonder, couldn't we as well use functions as macros by quoting their arguments (the form), transforming the form, evaluating it inside the function, finally returning it's value. Wouldn't this logically produce the same outcome? Of course this would be inconvenient, but theoretically, is there equivalent function for every possible macro?
Here is simple infix macro
(defmacro infix
"translate infix notation to clojure form"
[form]
(list (second form) (first form) (last form)))
(infix (6 + 6)) ;-> 12
Here is same logic using a function
(defn infix-fn
"infix using a function"
[form]
((eval (second form)) (eval (first form)) (eval (last form))))
(infix-fn '(6 + 6)) ;-> 12
Now, is this perception generalizable to all situations, or are there some corner cases where macro couldn't be outdone? In the end, are macros just a syntactic sugar over a function call?
eval
evaluates the form in a null lexical environment.(let [x 10] (infix-fn '(x + 6)))
=>CompilerException ... Unable to resolve symbol: x
– jkiiski