Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (defn proto-get [obj key]
- (cond
- (contains? obj key) (obj key)
- :else (proto-get (:prototype obj) key)))
- (defn field [key] (fn [name] (proto-get name key)))
- (defn method [key] (fn [this & args] (apply (proto-get this key) (cons this args))))
- (def evaluate (method :evaluate))
- (def toString (method :toString))
- (def diff (method :diff))
- (def operands (field :operands))
- (defn Constant [value]
- {
- :evaluate (fn [_ _] value)
- :toString (fn [_] (format "%.1f" value))
- :diff (fn [_ _] (Constant 0))
- })
- (defn Variable [name]
- {
- :evaluate (fn [_ map] (get map name))
- :toString (fn [_] (str name))
- :diff (fn [_ v] (if (= v name) (Constant 1) (Constant 0)))
- })
- (defn OperationFactory [action symbol howToDiff]
- (fn [& args]
- {:prototype {:evaluate (fn [this vars]
- (apply ((field :action) this) (mapv #(evaluate % vars) (operands this))))
- :toString (fn [this]
- (str "("
- ((field :symbol) this)
- (apply str (mapv #(str " " (toString %)) (operands this)))
- ")"))}
- :action action
- :symbol symbol
- :diff howToDiff
- :operands args}
- ))
- (defn nth-among-operands [this x] (nth (operands this) x))
- (def Add
- (OperationFactory
- +
- "+"
- (fn [this v]
- (Add (diff (nth-among-operands this 0) v)
- (diff (nth-among-operands this 1) v)))))
- (def Subtract
- (OperationFactory
- -
- "-"
- (fn [this v]
- (Subtract (diff (nth-among-operands this 0) v)
- (diff (nth-among-operands this 1) v)))))
- (def Negate
- (OperationFactory
- -
- "negate"
- (fn [this v]
- (Negate (diff (nth-among-operands this 0) v)))))
- (def Multiply
- (OperationFactory
- *
- "*"
- (fn [this v]
- (Add
- (Multiply (diff (nth-among-operands this 0) v) (nth-among-operands this 1))
- (Multiply (diff (nth-among-operands this 1) v) (nth-among-operands this 0)))
- )))
- (def Divide
- (OperationFactory
- (fn rec
- ([a b] (/ (double a) b))
- ([a b & more] (apply rec (rec a b) more)))
- "/"
- (fn [this v]
- (Divide
- (Subtract
- (Multiply (diff (nth-among-operands this 0) v) (nth-among-operands this 1))
- (Multiply (diff (nth-among-operands this 1) v) (nth-among-operands this 0)))
- (Multiply (nth-among-operands this 1) (nth-among-operands this 1))))))
- (def SqrtWithNegationIfNan
- (OperationFactory
- #(if (> % 0)
- (Math/sqrt (double %))
- (* (Math/sqrt (Math/abs (double %))) -1)
- )
- "sqrt"
- (fn [this v]
- (Divide (diff (nth-among-operands this 0) v)
- (Multiply (Constant 2) (SqrtWithNegationIfNan (nth-among-operands this 0))))
- )))
- (def Sqrt
- (OperationFactory
- #(Math/sqrt (Math/abs (double %)))
- "sqrt"
- (fn [this v]
- (diff (SqrtWithNegationIfNan (nth-among-operands this 0)) v)
- )))
- (def Square
- (OperationFactory
- #(* % %)
- "square"
- (fn [this v]
- (diff (Multiply (nth-among-operands this 0) (nth-among-operands this 0)) v)
- )))
- (def obj-operations {'+ Add
- '- Subtract
- '* Multiply
- '/ Divide
- 'negate Negate
- 'sqrt Sqrt
- 'square Square
- })
- (defn parseList [s]
- (if (list? s)
- (apply (get obj-operations (first s)) (map parseList (rest s)))
- (if (number? s)
- (Constant s)
- (Variable (str s)))
- )
- )
- (def parseObject #(parseList (read-string %)))
- ;(pr (evaluate (diff (Square (Subtract (Variable "x") (Variable "y"))) "x") {"z" 1.0, "x" 1.0, "y" 1.0}))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement