Created
September 27, 2010 18:31
-
-
Save jneira/599553 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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