Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (declare diff-factory)
- (declare Variable)
- (declare Add)
- (declare Subtract)
- (declare Multiply)
- (declare Divide)
- (declare Negate)
- (declare Sin)
- (declare Cos)
- (declare df)
- (defn proto-get [obj key]
- (cond
- (contains? obj key) (obj key)
- (contains? obj :prototype) (proto-get (:prototype obj) key)))
- (defn proto-call [obj key & args]
- (apply (proto-get obj key) (cons obj args)))
- (defn field [key]
- (fn [obj] (proto-get obj key)))
- (defn method [key]
- (fn [obj & args] (apply (partial proto-call obj key) args)))
- (defn constructor [ctor prototype operation symbol]
- (fn [& args] (apply (partial ctor {:prototype prototype :operation operation :symbol symbol}) args)))
- (def diff (method :diff))
- (def evaluate (method :evaluate))
- (def toString (method :toString))
- (def _left (field :left))
- (def _right (field :right))
- (def _value (field :value))
- (declare Constant)
- (def ConstPrototype
- {:evaluate (fn [this vals] (:value this))
- :toString (fn [this] (str (:value this)))
- :diff (fn [this var] (Constant 0))})
- (def VariablePrototype
- {:evaluate (fn [this vals] (vals (:name this)))
- :toString (fn [this] (:name this))
- :diff (fn [this var]
- ;(println var)
- (if (= var (:name this))
- (Constant 1)
- (Constant 0)))})
- (def BinaryOperationPrototype
- {:evaluate (fn [this vals] (apply (:operation this) (map #(evaluate % vals) (:args this))))
- :toString (fn [this] (str (:symbol this) " " (clojure.string/join " " (map #(toString %) (:args this)))))
- :diff (fn [this var] (df this var (:args this)))
- })
- (defn ConstFactory [this value]
- (assoc this
- :value value))
- (defn VariableFactory [this name]
- (assoc this
- :name name))
- (defn BinaryOperation [this & args]
- (assoc this
- :args args))
- (def Add (constructor BinaryOperation BinaryOperationPrototype (fn [& xs] (apply + xs)) "+"))
- (def Multiply (constructor BinaryOperation BinaryOperationPrototype (fn [& xs] (apply * xs)) "*"))
- (def Subtract (constructor BinaryOperation BinaryOperationPrototype (fn [& xs] (apply - xs)) "-"))
- (def Divide (constructor BinaryOperation BinaryOperationPrototype (fn [a b] (/ ^double a ^double b)) "/"))
- (def Negate (constructor BinaryOperation BinaryOperationPrototype (fn [a] (- a)) "negate"))
- (def Sin (constructor BinaryOperation BinaryOperationPrototype (fn [a] (Math/sin a)) "sin"))
- (def Cos (constructor BinaryOperation BinaryOperationPrototype (fn [a] (Math/cos a)) "cos"))
- (def Constant (constructor ConstFactory ConstPrototype + "+"))
- (def Variable (constructor VariableFactory VariablePrototype + "+"))
- (def obj-by-symbol
- {"+" Add
- "-" Add
- "*" Multiply
- "/" Divide
- "sin" Sin
- "cos" Cos
- "negate" Negate})
- (defn df [this var args]
- (cond
- (= (count args) 1) ((diff-factory (:symbol this) var) (nth args 0))
- (= (count args) 2) ((diff-factory (:symbol this) var) (nth args 0) (nth args 1))
- :else ((diff-factory (:symbol this) var) (nth args 0) (apply (obj-by-symbol (:symbol this)) (rest args)))))
- (defn diff-factory [symbol var]
- (cond
- (= symbol "+") (fn [& args] (apply Add (map #(diff % var) args)))
- (= symbol "-") (fn [& args] (apply Subtract (map #(diff % var) args)))
- (= symbol "*") (fn [& args] (if (> (count args) 1)
- (Add (Multiply (diff (nth args 0) var) (nth args 1)) (Multiply (nth args 0) (diff (nth args 1) var)))
- (diff (nth args 0) var)))
- (= symbol "/") (fn [left right] (Divide (Subtract (Multiply (diff left var) right) (Multiply left (diff right var))) (Multiply right right)))
- (= symbol "negate") (fn [left] (Negate (diff left var)))
- (= symbol "sin") (fn [left] (Multiply (Cos left) (diff left var)))
- (= symbol "cos") (fn [left] (Negate (Multiply (Sin left) (diff left var))))))
- (declare parse)
- (defn parse-token [r]
- (if (list? r)
- (parse r)
- (cond
- (= r 'x) (Variable "x")
- (= r 'y) (Variable "y")
- (= r 'z) (Variable "z")
- :else (Constant r))))
- (defn parse [r]
- (def x (first r))
- (cond
- (= x '+) (apply Add (map parse-token (rest r)))
- (= x '-) (apply Subtract (map parse-token (rest r)))
- (= x '*) (apply Multiply (map parse-token (rest r)))
- (= x 'negate) (apply Negate (map parse-token (rest r)))
- (= x 'sin) (apply Sin (map parse-token (rest r)))
- (= x 'cos) (apply Cos (map parse-token (rest r)))
- :else (apply Divide (map parse-token (rest r)))
- ))
- (defn parseObject [s]
- (def r (read-string s))
- (parse-token r))
- ;(def expr (parseFunction "(negate 5)"))
- (println (toString (diff (Subtract (Variable "x") (Variable "y") (Variable "z")) "z")))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement