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