3 points by fallintothis 3055 days ago | link | parent Whoa, whacky idea alert. What if we use whitespace to indicate operator precedence?Ha! File that under "never would've thought of it". Still think prefix does just fine, but I like that idea for its quirkiness.Also, I think you underestimate how generally useful perform can be :)Superficially contemplating perform (namely the fact that it's a macro) made me think of one thing I wish I had while writing infix. pop is a macro, so I couldn't pass it to map, proper. What I needed was a macro to map macros:`````` ; Goofy-looking name, but bear with me (mac macmap (m . exprs) `(list ,@(map [list m _] exprs))) `````` Thus`````` (push (list (pop ops) (pop (cdr prefix)) (pop prefix)) prefix) `````` becomes`````` (push (macmap pop ops (cdr prefix) prefix) prefix) `````` Which got me thinking: why did perform need to be a macro again? Well, obviously`````` (sum [apply * _] (list (q q) (2 p q))) `````` tries to eval (q q) and (2 p q), and writing (list q q) defeats the purpose of brevity. (Side note: in vanilla Arc, you couldn't use q.q, because ssyntax isn't expanded before macros.)Then I actually double-checked your original definition of perform and realized (macmap pop ...) = (perform list pop ...). So I've found my own example! But I think we might could do one better.What if I called it poly for polynomial?poly is too specific, if this operator hopes to be general. The operation itself smacks more of distributivity---almost like distributing an operator over cons. Emphasis on "an" operator, not a pair of them (lest it read like "distribute addition over multiplication"). But because (macmap ...) = (perform list ...), maybe it's just a better name for macmap:`````` (mac distribute (op . exprs) `(list ,@(map [list op _] exprs))) ; Thus (distribute pop ops (cdr prefix) prefix) `````` If we were to make perform a single-operator macro, a similarity I should've noticed earlier appears: it's almost the same as macmap, except`````` (mac distribute (op . exprs) `(list ,@(map [cons op _] exprs))) ; cons vs list! ; Thus (apply + (distribute * (q q) (2 p q))) `````` Not that the above is the best rewrite of the original, but if it were...is there a way to reconcile the cons vs list difference, whether by different names or by merging it into a super-distribute?
 1 point by akkartik 3055 days ago | link This is a super neat rewrite of the original. I don't have have much to contribute in response except tangents.1. I didn't pay attention to your implementation earlier, but this is insane:`````` (list (pop ops) (pop (cdr prefix)) (pop prefix)) `````` How the heck does this work? I replace cdr.prefix with just prefix and it works fine except that it reverses the order of the operands.. Ooh, I see:`````` arc> (= x '(1 2 3)) (1 2 3) arc> (pop cdr.x) 2 arc> x (1 3) `````` Mind.. blown. Of course, it makes sense with hindsight.Still, way too clever for my taste to rely on arg eval order. I'd rather make the ordering of mutations explicit:`````` (withs (b pop.prefix a pop.prefix) (push (list pop.ops a b) prefix)) `````` (with would still rely on arg eval order, I think.)2. "Still think prefix does just fine.."Absolutely. I'm not sure infix is worthwhile, just mildly dissatisfied by how arithmetic expressions in lisp turn out.3. It turns out David Wheeler has thoroughly thought through the various scenarios for infix precedence: http://sourceforge.net/p/readable/wiki/Precedence. I haven't digested it yet.4. "poly is too specific."Yes, I was being lazy. I imagined poly without operator parameters:`````` (poly q.q 2.p.q) `````` 5. "Emphasis on _an_ operator, not a pair of them (lest it read like 'distribute addition over multiplication')."That was incredibly useful in following your comment.6. Can I prevail on you to switch from zero to zero?? :)-----