Thanks for the example, the macro is exactly the solution was looking for.
On Nov 30, 1:11 am, Jeff Bester <[EMAIL PROTECTED]> wrote: > On Nov 28, 11:11 pm, Dmitri <[EMAIL PROTECTED]> wrote: > > > Thanks for the comments, the prefix notation may indeed be something > > that one gets used to. I find it just fine for most cases, just not > > for mathematical expressions. The example function was not meant as a > > complete solution, but rather as an example of how trivial it is to > > switch between the two notations. I do see how the formatting makes it > > more readable, thanks for pointing that out. It does sound that it's > > largely a matter of what you're used to. > > If you are translating formulas it might be worth investing the time > to > create a macro to convert from infix to prefix with precedence rules, > as > well as, creating new operators. I think Peter Norvig covers > something > akin to this in PAIP. This is where any lisp truly shines; that is > using > macros to express Domain Specific Languages. That is at compile/load > time > morph the code to allow new syntax in the language. > > See the following for an example implementation > > user> (formula (3 + 4 * 2) / 3) > 11/3 > > ===== Example code ==== > > ;; used for order of evaluation table and for valid infix operators > (def +precedence+ > {'rem 5, > '* 4, > '/ 3, > '+ 2, > '- 1}) > > ;; highest level of precedence > (def +highest-precedence+ (apply max (map val +precedence+))) > > (defn- operator? > "Check if is valid operator" > ([sym] > (not (nil? (get +precedence+ sym))))) > > (defn- find-lowest-precedence > "find the operator with lowest precedence; search from left to > right" > ([seq] > ;; loop through terms in the sequence > (loop [idx 0 > seq seq > lowest-idx nil > lowest-prec +highest-precedence+] > ;; nothing left to process > (if (empty? seq) > ;; return lowest found > lowest-idx > ;; otherwise check if current term is lower > (let [prec (get +precedence+ (first seq))] > ;; is of lower or equal precedence > (if (and prec (<= prec lowest-prec)) > (recur (inc idx) (rest seq) > idx prec) > ;; is of high precedence therefore skip for now > (recur (inc idx) (rest seq) > lowest-idx lowest-prec))))))) > > (defn- infix-to-prefix > "Convert from infix notation to prefix notation" > ([seq] > (cond > ;; handle term only > (not (seq? seq)) seq > ;; handle sequence containing one term (i.e. handle parens) > (= (count seq) 1) (infix-to-prefix (first seq)) > ;; handle all other cases > true (let [lowest (find-lowest-precedence seq)] > (if (nil? lowest) ;; nothing to split > seq > ;; (a b c) bind a to hd, c to tl, and b to op > (let [[hd tl] (split-at lowest seq) > op (first tl) > tl (rest tl)] > ;; recurse > (list op (infix-to-prefix hd) (infix-to-prefix tl)))))))) > > (defmacro formula > "Formula macro translates from infix to prefix" > ([& equation] > (infix-to-prefix equation)) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---