Touch the firehose of ds106, the most recent flow of content from all of the blogs syndicated into ds106. As of right now, there have been 92388 posts brought in here going back to December 2010. If you want to be part of the flow, first learn more about ds106. Then, if you are truly ready and up to the task of creating web art, sign up and start doing it.

Revisiting Macros – the -> Operator

Posted by

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:

(defn evalpop [myVal myList]
(if (= myList ())
; 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
(evalpop (eval(cons(first(first myList))(cons myVal (rest(first myList))))) (rest myList))))
There’s a big chunk.  I’m thinking, however, that this may be possible without macro use.  I’ll try that first, then see if macros make it easier.
Ok so I’m still here, just tested a new function:
(defn >>> [myList] (evalpop(eval(first myList))(rest myList)))
and it almost works just like the -> operator, except it’s taking a list as the arg, denoted by a ‘ preceding a parenthesized list of items
Action Shot:
I’ve got a feeling that from here I’ll just need macros to tie it all in to make it so I won’t have to use the list marker, just have to enter one!

Add a comment

ds106 in[SPIRE]