clojurewerkz / money

A Clojure library that deals with monetary values and currencies. Built on top of Joda Money.
155 stars 20 forks source link

multiply/divide with BigDecimal #20

Closed jgeraerts closed 8 years ago

jgeraerts commented 8 years ago

This clojure wrapper uses type hints to make the multiplier explicitly a double, probably to avoid reflection warnings. However the joda money java library also has a multiplied by method taking a BigDecimal as multiplier. Currently this cannot be used from this library.

I'm willing to add this functionality, but it is unclear to me how to proceed in a idiomatic way:

michaelklishin commented 8 years ago

Joda Time has "type hints" (signatures) by definition ;) You can use a single function that then dispatches to a protocol (and not a multi-method), where each implementation has a type hint.

jgeraerts commented 8 years ago

And then swap the arguments in the Protocol function so i can dispatch on the multiplier type?

michaelklishin commented 8 years ago

Simply delegate to the protocol function. It should avoid reflection (which is the point of type hints).

On 1 abr 2016, at 12:38, Jo Geraerts notifications@github.com wrote:

And then swap the arguments in the Protocol function so i can dispatch on the multiplier type?

— You are receiving this because you commented. Reply to this email directly or view it on GitHub

jgeraerts commented 8 years ago

So for example your current function multiply

(defn ^Money multiply
  ([^Money money ^double multiplier]
     (.multipliedBy money multiplier (cnv/to-rounding-mode nil)))
  ([^Money money ^double multiplier rounding-mode]
     (.multipliedBy money multiplier (cnv/to-rounding-mode rounding-mode))))

would become

(defprotocol AmountOps
  (op-multiply [multiplier money rounding-mode]))

(extend-protocol AmountOps
  double
  (op-multiply [multiplier ^Money money rounding-mode]
    (.multipliedBy money multiplier rounding-mode))
  java.math.BigDecimal
  (op-multiply [multiplier ^Money money rounding-mode]
    (.multipliedBy money multiplier rounding-mode)))

(defn ^Money multiply
  ([^Money money ^double multiplier]
     (op-multiply multiplier money (cnv/to-rounding-mode nil)))
  ([^Money money ^double multiplier rounding-mode]
     (op-multiply multiplier money (cnv/to-rounding-mode rounding-mode))))

And then ofcourse similar for the other operations. The only thing i feel dirty about is the parameter order in the protocol, especially for op-minus it gets counter intuitive.

michaelklishin commented 8 years ago

That actually might be nicer than what I had in mind. We still need to drop the type hint from multiply.

jgeraerts commented 8 years ago

alright, i'll work it out.