I'm starting out with Clojure, which is also my first lisp. There's obviously a lot to take in, and in an attempt to lessen the cognitive load, I try to find the parts which I can safely ignore (for now).
Can one safely treat forms with macros and forms with built-ins the same, or are there pitfalls that will spring up later?
In other words, will I ever run into a situation where I need to know that (defn f1 [])
expands to
(def f1 (.withMeta (clojure.core/fn f1 ([])) (.meta (var f1))))
Macros in general compose very differently. Macros are not "first class citizens": you can't pass them to map
etc., you can't store them in variables and you can't apply
them to a list of arguments. Initially you don't need to worry about these because they will obviously not work: a subtle, hard-to-detect error would be a lot more troubling. If you try to run
(map if [true false true false] [1 2 3 4] [-1 -2 -3 -4])
the fact that if is not a function will become very apparent. Just keep in mind that macros are not functions and you should be just fine :)
PS: macros are (fn (fn (fn :-D) :^P) :O)
In almost all cases you can completely ignore the distinction. (and in fact you have, since fn isn't a built in either - it's a macro expanding to fn*)
The only exception I've come across is that macros and built-ins behave differently if you try to redefine them. Just don't redefine any existing functionality and you'll be fine treating them the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With