I was finally forced into the realms of macros. What I wanted was this:
(defn logic-tree [gate1 gate2 gate3]
(fn [a b c d] (gate1 (gate2 a b) (gate3 c d))))
My idea was to be able to write a function that generated a function which took four args and combined them in a logic gate, like this:
(gate1 (gate2 A B) (gate3 C D))
(AND (OR A B) (NAND C D))
This is not possible to solve with a function, since a function cannot easily distinguish between the functional arguments and the arguments to feed in later on. This meant I had to go for macros, which have always scared me.
Learning clojure has a good tutorial.
(defmacro logic4 [f]
(list 'fn ['a 'b]
(list f 'a 'b)))
(macroexpand '(logic4 and))
;;=> (fn* ([a b] (and a b)))
((logic4 and) true true) => true
which would easily be expanded to the final form.
Macros does seem less scary after this.