Advertisement
Guest User

Untitled

a guest
May 26th, 2015
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (declare diff-factory)
  2. (declare Variable)
  3. (declare Add)
  4. (declare Subtract)
  5. (declare Multiply)
  6. (declare Divide)
  7. (declare Negate)
  8. (declare Sin)
  9. (declare Cos)
  10. (declare df)
  11.  
  12. (defn proto-get [obj key]
  13.     (cond
  14.       (contains? obj key) (obj key)
  15.       (contains? obj :prototype) (proto-get (:prototype obj) key)))
  16.  
  17. (defn proto-call [obj key & args]
  18.   (apply (proto-get obj key) (cons obj args)))
  19.  
  20. (defn field [key]
  21.   (fn [obj] (proto-get obj key)))
  22.  
  23. (defn method [key]
  24.   (fn [obj & args] (apply (partial proto-call obj key) args)))
  25.  
  26. (defn constructor [ctor prototype operation symbol]
  27.   (fn [& args] (apply (partial ctor {:prototype prototype :operation operation :symbol symbol}) args)))
  28.  
  29. (def diff (method :diff))
  30. (def evaluate (method :evaluate))
  31. (def toString (method :toString))
  32. (def _left (field :left))
  33. (def _right (field :right))
  34. (def _value (field :value))
  35.  
  36. (declare Constant)
  37.  
  38. (def ConstPrototype
  39.   {:evaluate (fn [this vals] (:value this))
  40.    :toString (fn [this] (str (:value this)))
  41.    :diff (fn [this var] (Constant 0))})
  42.  
  43. (def VariablePrototype
  44.   {:evaluate (fn [this vals] (vals (:name this)))
  45.    :toString (fn [this] (:name this))
  46.    :diff (fn [this var]
  47.            ;(println var)
  48.            (if (= var (:name this))
  49.                           (Constant 1)
  50.                           (Constant 0)))})
  51.  
  52. (def BinaryOperationPrototype
  53.   {:evaluate (fn [this vals] (apply (:operation this) (map #(evaluate % vals) (:args this))))
  54.    :toString (fn [this] (str (:symbol this) " " (clojure.string/join " " (map #(toString %) (:args this)))))
  55.    :diff (fn [this var] (df this var (:args this)))
  56.    })
  57.  
  58. (defn ConstFactory [this value]
  59.   (assoc this
  60.     :value value))
  61.  
  62. (defn VariableFactory [this name]
  63.   (assoc this
  64.     :name name))
  65.  
  66. (defn BinaryOperation [this & args]
  67.   (assoc this
  68.     :args args))
  69.  
  70. (def Add (constructor BinaryOperation BinaryOperationPrototype (fn [& xs] (apply + xs)) "+"))
  71. (def Multiply (constructor BinaryOperation BinaryOperationPrototype (fn [& xs] (apply * xs)) "*"))
  72. (def Subtract (constructor BinaryOperation BinaryOperationPrototype (fn [& xs] (apply - xs)) "-"))
  73. (def Divide (constructor BinaryOperation BinaryOperationPrototype (fn [a b] (/ ^double a ^double b)) "/"))
  74. (def Negate (constructor BinaryOperation BinaryOperationPrototype (fn [a] (- a)) "negate"))
  75. (def Sin (constructor BinaryOperation BinaryOperationPrototype (fn [a] (Math/sin a)) "sin"))
  76. (def Cos (constructor BinaryOperation BinaryOperationPrototype (fn [a] (Math/cos a)) "cos"))
  77. (def Constant (constructor ConstFactory ConstPrototype + "+"))
  78. (def Variable (constructor VariableFactory VariablePrototype + "+"))
  79.  
  80. (def obj-by-symbol
  81.   {"+" Add
  82.    "-" Add
  83.    "*" Multiply
  84.    "/" Divide
  85.    "sin" Sin
  86.    "cos" Cos
  87.    "negate" Negate})
  88.  
  89. (defn df [this var args]
  90.   (cond
  91.     (= (count args) 1) ((diff-factory (:symbol this) var) (nth args 0))
  92.     (= (count args) 2) ((diff-factory (:symbol this) var) (nth args 0) (nth args 1))
  93.     :else ((diff-factory (:symbol this) var) (nth args 0) (apply (obj-by-symbol (:symbol this)) (rest args)))))
  94.  
  95. (defn diff-factory [symbol var]
  96.   (cond
  97.     (= symbol "+") (fn [& args] (apply Add (map #(diff % var) args)))
  98.     (= symbol "-") (fn [& args] (apply Subtract (map #(diff % var) args)))
  99.     (= symbol "*") (fn [& args] (if (> (count args) 1)
  100.                                   (Add (Multiply (diff (nth args 0) var) (nth args 1)) (Multiply (nth args 0) (diff (nth args 1) var)))
  101.                                   (diff (nth args 0) var)))
  102.     (= symbol "/") (fn [left right] (Divide (Subtract (Multiply (diff left var) right) (Multiply left (diff right var))) (Multiply right right)))
  103.     (= symbol "negate") (fn [left] (Negate (diff left var)))
  104.     (= symbol "sin") (fn [left] (Multiply (Cos left) (diff left var)))
  105.     (= symbol "cos") (fn [left]  (Negate (Multiply (Sin left) (diff left var))))))
  106.  
  107. (declare parse)
  108.  
  109. (defn parse-token [r]
  110.   (if (list? r)
  111.     (parse r)
  112.     (cond
  113.       (= r 'x) (Variable "x")
  114.       (= r 'y) (Variable "y")
  115.       (= r 'z) (Variable "z")
  116.       :else (Constant r))))
  117.  
  118. (defn parse [r]
  119.   (def x (first r))
  120.  
  121.   (cond
  122.     (= x '+) (apply Add (map parse-token (rest r)))
  123.     (= x '-) (apply Subtract (map parse-token (rest r)))
  124.     (= x '*) (apply Multiply (map parse-token (rest r)))
  125.     (= x 'negate) (apply Negate (map parse-token (rest r)))
  126.     (= x 'sin) (apply Sin (map parse-token (rest r)))
  127.     (= x 'cos) (apply Cos (map parse-token (rest r)))
  128.     :else (apply Divide (map parse-token (rest r)))
  129.     ))
  130.  
  131. (defn parseObject [s]
  132.   (def r (read-string s))
  133.   (parse-token r))
  134.  
  135. ;(def expr (parseFunction "(negate 5)"))
  136.  
  137. (println (toString (diff (Subtract (Variable "x") (Variable "y") (Variable "z")) "z")))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement