Skip to content

Instantly share code, notes, and snippets.

@jneira
Created September 27, 2010 18:31
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jneira/599553 to your computer and use it in GitHub Desktop.
Save jneira/599553 to your computer and use it in GitHub Desktop.
(defprotocol TradeTax
(trade-tax [trade logic]))
(defprotocol Commission
(commission [trade logic]))
(defrecord Trade [ref-no account instrument principal tax-fees
unit-price quantity])
(defn calculate-tax [{:keys [principal]} logic]
(logic principal))
(defn calculate-commission [{:keys [principal quantity]} logic]
(logic principal quantity))
;;protocols statically bind
;;(commented and mixin impl with maps in http://sbtourist.blogspot.com/2010/09/dynamic-mixins-in-clojure-experiment.html)
(comment extend Trade
TradeTax
{:trade-tax calculate-tax}
Commission
{:commission calculate-commission})
(defn create-trade
[{:keys [ref-no account instrument unit-price quantity]
:as request}]
(Trade. ref-no account instrument (* unit-price quantity) {}
unit-price quantity))
;;0x3b a sample request
(def request
{:ref-no "trd-123"
:account "nomura-123"
:instrument "IBM"
:unit-price 120
:quantity 300})
(def my-trade (create-trade request))
(defn with-commission [t]
(reify Commission
(commission [_ logic] (calculate-commission t logic))))
(defn with-trade-tax [t]
(reify TradeTax
(trade-tax [_ logic] (calculate-tax t logic))))
(def my-trade-tax (trade-tax (with-trade-tax my-trade) #(* % 0.05)))
(def my-commission
(commission (with-commission my-trade)
(fn [p q] (* p (if (> q 100) 0.05 0.07)))))
(def my-trade-tax2 (calculate-tax {:principal 36000} #(* % 0.05)))
(def my-commission2
(calculate-commission
{:principal 36000 :quantity 300}
(fn [p q] (* p (if (> q 100) 0.05 0.07)))))
(assert (= my-trade-tax my-trade-tax2))
(assert (= my-commission my-commission2))
;; decorator impl in http://debasishg.blogspot.com/2010/09/domain-models-thinking-differently-in.html
(comment
(defn trade
"Make a trade from the request"
[request]
{:ref-no (:ref-no request)
:account (:account request)
:instrument (:instrument request)
:principal (* (:unit-price request) (:quantity request))
:tax-fees {}})
(defn with-values [trade tax-fee value]
(fn [request]
(let [trdval (trade request)
principal (:principal trdval)]
(assoc-in trdval [:tax-fees tax-fee]
(* principal (/ value 100))))))
;; from compojure source
(defmacro redef
"Redefine an existing value, keeping the metadata intact."
[name value]
`(let [m# (meta (var ~name))
v# (def ~name ~value)]
(alter-meta! v# merge m#)
v#))
; macro to decorate a function
(defmacro with-tax-fee
"Wrap a function in one or more decorators"
[func & decorators]
`(redef ~func (-> ~func ~@decorators)))
(with-tax-fee trade
(with-values :tax 12)
(with-values :commission 23)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment