Difference between using list and back tick in macros - clojure

At a conceptual level a macro in LISP (and dialects) take a piece of code (as list) and returns another piece of code (again as list).
Based on above principle a simple macro could be:
(defmacro zz [a] (list print a))
;macroexpand says : (#<core$print clojure.core$print#749436> "Hello")
But in clojure this can also be written as:
(defmacro zz [a] `(print ~a))
;macroexpand says : (clojure.core/print "Hello")
I am not exactly sure about the difference here and which should be the preferred way. The first one look simple as we are supposed to return list and avoid using weird characters like back tick.

No one has pointed this out yet...the difference between your 2 macros is this: your second form (using backtick)
(defmacro zz [a] `(print ~a))
is equivalent to:
(defmacro zz [a] (list 'print a))
Which is different from your first example:
(defmacro zz [a] (list print a))
Note the missing single quote -- that is why your macroexpand is different. I agree with the other people posting: using backquote is more conventional if your macro has a fairly simple 'shape'. If you have to do code walking or dynamic construction (i.e. a complex macro), then using lists and building it up is often what's done.
I hope this explanation makes sense.

Constructing lists explicitly is "simplest", in a way, because there are few core concepts you need to know: just accept a list and change it around till you have a new list. Backtick is a convenient shortcut for "templating" chunks of code; it is possible to write any macro without it, but for any large macro it quickly becomes very unpleasant. For example, consider two ways of writing let as a macro over fn:
(defmacro let [bindings & body]
(let [names (take-nth 2 bindings)
vals (take-nth 2 (rest bindings))]
`((fn [~#names]
(do ~#body))
~#vals)))
(defmacro let [bindings & body]
(let [names (take-nth 2 bindings)
vals (take-nth 2 (rest bindings))]
(cons (list `fn (vec names) (cons `do body))
vals)))
In the first case, using backtick makes it fairly clear that you're writing a function of the names containing the body, and then calling it with the values - the macro code is "shaped" the same as the expansion code, so you can imagine what it will look like.
In the second case, with just cons and list all over the place, it is a real headache to work out what the expansion will look like. This isn't always the case, of course: sometimes it can be clearer to write something without a backtick.
Another very important point was made by Kyle Burton: print is not the same as 'print! Your macro expansion should contain the symbol print, not its value (which is a function). Embedding objects (such as functions) in code is very fragile and only works by accident. So make sure your macros expand to code you could actually have written yourself, and let the evaluation system do the hard work - you could type in the symbol print, but you couldn't type in a pointer to the current value of the function print.

There's a style difference between them. Your example is very simple but in more complex macros the difference will be bigger.
For example the unless macro as defined in "The Joy of Clojure" book:
(defmacro unless [condition & body]
`(if (not ~condition)
(do ~#body)))
From the book:
Syntax-quote allows the following if-form to act as a sort of template for the expression
that any use of the macro become when it is expanded.
When creating a macro always choose the most readable and idiomatic style.
To contrast, the above code can equivalently be written like so:
(defmacro unless [condition & body]
(list 'if (list 'not condition)
(list* 'do body)))

In my experience they are equivalent. Though there may be some edge cases I'm not aware of.
#islon 's example can equivalently be written as:
To contrast, the above code can equivalently be written like so:
(defmacro unless [condition & body]
(list 'if (list 'not condition)
(list* 'do body)))

Related

Functional alternative to "let"

I find myself writing a lot of clojure in this manner:
(defn my-fun [input]
(let [result1 (some-complicated-procedure input)
result2 (some-other-procedure result1)]
(do-something-with-results result1 result2)))
This let statement seems very... imperative. Which I don't like. In principal, I could be writing the same function like this:
(defn my-fun [input]
(do-something-with-results (some-complicated-procedure input)
(some-other-procedure (some-complicated-procedure input)))))
The problem with this is that it involves recomputation of some-complicated-procedure, which may be arbitrarily expensive. Also you can imagine that some-complicated-procedure is actually a series of nested function calls, and then I either have to write a whole new function, or risk that changes in the first invocation don't get applied to the second:
E.g. this works, but I have to have an extra shallow, top-level function that makes it hard to do a mental stack trace:
(defn some-complicated-procedure [input] (lots (of (nested (operations input)))))
(defn my-fun [input]
(do-something-with-results (some-complicated-procedure input)
(some-other-procedure (some-complicated-procedure input)))))
E.g. this is dangerous because refactoring is hard:
(defn my-fun [input]
(do-something-with-results (lots (of (nested (operations (mistake input))))) ; oops made a change here that wasn't applied to the other nested calls
(some-other-procedure (lots (of (nested (operations input))))))))
Given these tradeoffs, I feel like I don't have any alternatives to writing long, imperative let statements, but when I do, I cant shake the feeling that I'm not writing idiomatic clojure. Is there a way I can address the computation and code cleanliness problems raised above and write idiomatic clojure? Are imperitive-ish let statements idiomatic?
The kind of let statements you describe might remind you of imperative code, but there is nothing imperative about them. Haskell has similar statements for binding names to values within bodies, too.
If your situation really needs a bigger hammer, there are some bigger hammers that you can either use or take for inspiration. The following two libraries offer some kind of binding form (akin to let) with a localized memoization of results, so as to perform only the necessary steps and reuse their results if needed again: Plumatic Plumbing, specifically the Graph part; and Zach Tellman's Manifold, whose let-flow form furthermore orchestrates asynchronous steps to wait for the necessary inputs to become available, and to run in parallel when possible. Even if you decide to maintain your present course, their docs make good reading, and the code of Manifold itself is educational.
I recently had this same question when I looked at this code I wrote
(let [user-symbols (map :symbol states)
duplicates (for [[id freq] (frequencies user-symbols) :when (> freq 1)] id)]
(do-something-with duplicates))
You'll note that map and for are lazy and will not be executed until do-something-with is executed. It's also possible that not all (or even not any) of the states will be mapped or the frequencies calculated. It depends on what do-something-with actually requests of the sequence returned by for. This is very much functional and idiomatic functional programming.
i guess the simplest approach to keep it functional would be to have a pass-through state to accumulate the intermediate results. something like this:
(defn with-state [res-key f state]
(assoc state res-key (f state)))
user> (with-state :res (comp inc :init) {:init 10})
;;=> {:init 10, :res 11}
so you can move on to something like this:
(->> {:init 100}
(with-state :inc'd (comp inc :init))
(with-state :inc-doubled (comp (partial * 2) :inc'd))
(with-state :inc-doubled-squared (comp #(* % %) :inc-doubled))
(with-state :summarized (fn [st] (apply + (vals st)))))
;;=> {:init 100,
;; :inc'd 101,
;; :inc-doubled 202,
;; :inc-doubled-squared 40804,
;; :summarized 41207}
The let form is a perfectly functional construct and can be seen as syntactic sugar for calls to anonymous functions. We can easily write a recursive macro to implement our own version of let:
(defmacro my-let [bindings body]
(if (empty? bindings)
body
`((fn [~(first bindings)]
(my-let ~(rest (rest bindings)) ~body))
~(second bindings))))
Here is an example of calling it:
(my-let [a 3
b (+ a 1)]
(* a b))
;; => 12
And here is a macroexpand-all called on the above expression, that reveal how we implement my-let using anonymous functions:
(clojure.walk/macroexpand-all '(my-let [a 3
b (+ a 1)]
(* a b)))
;; => ((fn* ([a] ((fn* ([b] (* a b))) (+ a 1)))) 3)
Note that the expansion doesn't rely on let and that the bound symbols become parameter names in the anonymous functions.
As others write, let is actually perfectly functional, but at times it can feel imperative. It's better to become fully comfortable with it.
You might, however, want to kick the tires of my little library tl;dr that lets you write code like for example
(compute
(+ a b c)
where
a (f b)
c (+ 100 b))

Clojure : Defining a forv macro using for

I'm trying to write my second macro but I'm completely stuck here.
I would like to avoid writing everytime (vec (for [...])) so I'm trying to write a forv macro like filterv, mapv, etc.
I work mostly with vectors in my programs since I need to have access to the index because I use external buffers/descriptors to fasten matrix process.
I have written many ***v like functions (also adaptative functions like fmap )but I'm sticked with for.
So I wrote
(defmacro forv
[seq-exprs body-expr]
(vec (for (vec seq-exprs) body-expr)))
I tried with seq-exprs alone, it does not work. To be honest I tried also ~ and so on but I do not know how it works, I succeed in my first macro because it was far easier.
Clojure tell me that for requires a vector for binding.
Can someone help me and also explain what I am missing ? Thanks !
You could use the one built into the Tupelo Library. Source code is here: https://github.com/cloojure/tupelo/blob/master/src/tupelo/core.cljc#L181
(defmacro forv
"Like clojure.core/for but returns results in a vector. Equivalent to (into [] (for ...)). Not
lazy."
[& body]
`(vec (for ~#body)))
;;
;; you want something like that in the end: (forv [x (range 2)] x) => (vec (for [x (range 2)] x))
;;
(defmacro forv
[seq-exprs body-expr]
`(vec (for [~#seq-exprs] ~body-expr)))
;;
;; check quote and unquote
;; in particular, check the tricky bit is https://clojuredocs.org/clojure.core/unquote-splicing
;;
Edit: I based my answer to mimic the original code in the question, but Alan's answer is better than mine.

Is there any macro(except declare) for writing functions without think of the order of function declarations in Clojure

I want to write functions without think of the order of function declarations, I don't want to use declare function because I need to declare all function names which I don't want to do it.
I want some macro or some function that does the magic for me. Long story short, I need to write functions like Java(method declaration order does not matter )
One of the best things I like most about functional programming is, that its flow of writing is the same as the flow of thinking. It's like peeling an onion, and at every moment, I only need to concentrate on working on this single layer, and take the inner part for granted. And don't worry about function names, foo and bar would be fine at first. In this style of writing, functions are defined and implemented from the end of the source file back to the top. In cases when one function calls multiple other functions, this linear structure becomes a tree-like structure, but there is always a single point in file to insert new functions. No choices and worries.
Yes, there are times when we need to work on some code snippets with no other dependencies. They can be put at the top of the source file of course.
To answer the question upfront, macros are not magic. If there exists such a macro, this macro will need to take the whole source file as input, analyze the dependency between each code blocks, and re-flow them in the correct order. The analysis of dependency is non-trivial because of lexical scoping. It's almost like writing a compiler. I don't believe such macro exists (has been written by anyone), and the goods it can do is, well to me, not so big.
It is kind of unneeded, but easily possible as an exercise (up to some point). You can write macro, that would forward declare all the top level functions wrapped in it:
(defmacro with-forward-declaration [& body]
(let [names (keep #(when (#{'defn 'defn-} (first %))
(if (map? (second %)) (nth % 2) (second %)))
body)]
`(do (declare ~#names)
~#body)))
that is how it is expanded:
(with-forward-declaration
(defn ^long ff1 [x] (* 2 (ff2)))
(println "just to be sure it doesn't eat other forms")
(defn ^{:name 'xx} ff2 [] (+ 10 (ff3)))
(defn ff3 [] 101)
(defn- ff4 [] :x))
would do the following:
(do
(declare ff1 ff2 ff3 ff4)
(defn ff1 [x] (* 2 (ff2)))
(println "just to be sure it doesn't eat other forms")
(defn ff2 [] (+ 10 (ff3)))
(defn ff3 [] 101)
(defn- ff4 [] :x))
so if you wrap all your namespace's code into this macro, it would predeclare all the functions for you. If you want to go deeper, like predeclaring all some possible defns that are not in the top level, you could update this toy macro by using clojure.walk to find these inner forms.. But i guess this one is just enough, to play with clojure quickly, without thinking about functions' order. I wouldn't do that in production though (at least not without the heavy testing).

How to pass a list to clojure's `->` macro?

I'm trying to find a way to thread a value through a list of functions.
Firstly, I had a usual ring-based code:
(defn make-handler [routes]
(-> routes
(wrap-json-body)
(wrap-cors)
;; and so on
))
But this was not optimal as I wanted to write a test to check the routes are actually wrapped with wrap-cors. I decided to extract the wrappers into a def. So the code became as follows:
(def middleware
(list ('wrap-json-body)
('wrap-cors)
;; and so on
))
(defn make-handler [routes]
(-> routes middleware))
This apparently doesn't work and is not supposed to as the -> macro doesn't take a list as the second argument. So I tried to use the apply function to resolve that:
(defn make-handler [routes]
(apply -> routes middleware))
Which eventually bailed out with:
CompilerException java.lang.RuntimeException: Can't take value of a
macro: #'clojure.core/->
So the question arises: How does one pass a list of values to the -> macro (or, say, any other macro) as one would do with apply for a function?
This is an XY Problem.
The main point of -> is to make code easier to read. But if one writes a new macro solely in order to use -> (in code nobody will ever see because it exists only at macro-expansion), it seems to me that this is doing a lot of work for no benefit. Moreover, I believe it obscures, rather than clarifies, the code.
So, in the spirit of never using a macro where functions will do, I suggest the following two equivalent solutions:
Solution 1
(reduce #(%2 %) routes middleware)
Solution 2
((apply comp middleware) routes)
A Better Way
The second solution is easily simplified by changing the definition of middleware from being a list of the functions to being the composition of the functions:
(def middleware
(comp wrap-json-body
wrap-cors
;; and so on
))
(middleware routes)
When I began learning Clojure, I ran across this pattern often enough that many of my early projects have an freduce defined in core:
(defn freduce
"Given an initial input and a collection of functions (f1,..,fn),
This is logically equivalent to ((comp fn ... f1) input)."
[in fs]
(reduce #(%2 %) in fs))
This is totally unnecessary, and some might prefer the direct use of reduce as being more clear. However, if you don't like staring at #(%2 %) in your application code, adding another utility word to your language is fine.
you can make a macro for that:
;; notice that it is better to use a back quote, to qoute function names for macro, as it fully qualifies them.
(def middleware
`((wrap-json-body)
(wrap-cors))
;; and so on
)
(defmacro with-middleware [routes]
`(-> ~routes ~#middleware))
for example this:
(with-middleware [1 2 3])
would expand to this:
(-> [1 2 3] (wrap-json-body) (wrap-cors))

Clojure macro puzzle: expanding sequence in macro args

This is not my 'production code' but a simplication of the problem for illustration purposes. Also, the title of this question is misleading because it brings to mind the ~# expansion, which I understand, and which may not necessarily be the problem. Please suggest a better question title if you can.
Given a macro with the following form:
(defmacro my-add [x & ys] `(+ ~x ~#ys))
Now let's say we have a list:
(def my-lst '(2 3))
Now I want a function that uses my-add that I can pass my-lst to as an arg, i.e.
(call-my-add 1 my-lst)
I define the function in what would seem to be the obvious way:
(defn call-my-add [x ys]
(apply my-add (cons x ys)))
But:
java.lang.Exception: Can't take value of a macro: #'user/call-my-add (repl-1:60)
I've tried all sorts of wild tricks to get the call-my-add function to work using evals, applies, and even defining call-my-add as a macro, but they all give similar ClassCastExceptions.
Is there any way out of this?
No. Macros do not, cannot, will never, have access to the actual run-time values contained in their arguments, so cannot splice them into the expansion. All they get is the symbol(s) you pass to them, in this case my-list. The "way around this" is to define my-add as a function, and then (optionally) have a macro that calls that function in order to generate its code.
I wrote a blog post about this semi-recently that you might find enlightening.
You could do it with evals if you wanted to, but that is a terrible idea in almost every case:
(let [my-list '(1 2)]
(eval `(my-add 5 ~#my-list)))
What a great example showing that macros are not first class citizens in Clojure (or any Lisp that I know of). They cannot be applied to functions, stored in containers, or passed to functions etc. In exchange for this they get to control when and if their arguments are evaluated.
What happens at macro expansion time must stay in macro expansion time. So if my-add is being evaluated at macro expansion time and you want to use apply then you need... another macro; to do the applying.
(defmacro call-my-add [x ys]
`(my-add ~#(cons x ys)))
Macros are somewhat contagious in this way.
PS: I'm not at my repl so please edit if you see a bug in this example (or I'll fix it when I get back)