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 [email protected]
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
-~----------~----~----~----~------~----~------~--~---