So I’m currently in the process of trying to get a better grasp of macros, got a link from my classmate Erin that helped explain them pretty well. I decided I would try to redefine a macro already pre-defined by the language, the -> operator. I mentioned it in a previous post, it overrides typical parenthetical groupings and allows a left to right evaluation of a list of commands
i.e. if you wanted to do ((9 + 5) / 7) * 16, you’d normally have to do…
(* 16 (/ (+ 9 5) 7)) in Clojure to get the result of 32
but with -> it gets a little prettier
(-> (+ 9 5) (/ 7) (* 16))
which returns the same result of 32. The -> takes a list of operations, evaluates the first operation, and passes the result into the next operation.
So to show somewhat of a stack trace for the operation above with ->, it would be
(+ 9 5) return 14, plug into next operation
(/ (14) 7) return 2, plug into next operation
(* (2) 16) return 32
Notice how the result of the last expression is the FIRST operand in the next operation. I wrote an algorithm to get a result from a previous expression inserted into that same slot. Given a list of operations (args) and a value (val) from a previous result the command:
(cons (first(first args)) (cons val (rest(first args)))) will write out the operation with the value in the correct location in the next operation. The cons operator concatenates an item to the beginning of a list, so I had to break it down a little bit. I started by concatenating the new value to the beginning of rest of the items of the first arg (cons val (rest(first(args)))) which just made a list of the operands. After that, I concatenated the first item of the first arg, or the operator, to that list, giving a list that could be evaluated as a legal operation using the eval function.
Now I’m kind of stuck. I’m working on it, but it’s somewhat of a challenge. I feel I’ll be defining the macro using a local function to do the recursive evaluation. Really not sure of how to do the macroexpansion or properly write the macro at this time. I feel I’ve got the algorithm down, and it’ll just be me trying to figure out the syntax and whatnot of macro writing. If you have input, it would be greatly appreciated.
=============A FEW HOURS LATER=================
Came back to the problem and did some work to try to find the potential local function, and I think I’ve succeeded:
; return the value if the list is empty
;otherwise insert the value into the first slot of the operation, and recurse with the evaluation of the first op as the new myVal
(defn >>> [myList] (evalpop(eval(first myList))(rest myList)))