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
-~----------~----~----~----~------~----~------~--~---

Reply via email to