I think this approach , no matter how decoupled it may be, HotSpot will have a hard time (if not impossible) inlining these fn-calls. The protocol approach you described will give you the best performance, especially if you type-hint your reify block. That said, for plugin type situations I prefer multi-methods because you don't have to declare/group any fns up front. Whenever you need extension point you just add a `defmethod`. For your use-case this means something like the following, which I'll admit is not very pretty... the general problem is that since you're doing numerical computation multi-methods are a bit of an overkill...when you generalise it a bit more though multi-methods are great...

(defmulti calculate (fn [operator _] operator))
(defmethod calculate + [_ data] (apply + data))
(defmethod calculate *  [_ data] (apply * data))

user=> (calculate + (range 100))
4950
user=> (calculate * (range 100))
0
user=> (calculate * (range 1 100))
ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1388)
user=> (calculate * (range 1 10))
362880

Jim

ps: another nice and functional approach would be this:

(defn make-calculator [operator]
   (fn [& data] (apply operator data)))

(defn calculate [calculator data]
  (apply calculator data))

which you call like this:

(-> (make-calculator +)
    (calculate (range 25)))
=>300

HTH, :)


On 05/06/13 11:55, Moritz Ulrich wrote:
If you want to keep this style, why not use a simple map of function
instead of reifying a protocol? Something like:

(defn calc-multiply [data] ...)
(defn calc-add [data] ...)
(defn make-calc [] {:calc-add #'calc-add, :calc-multiply #'calc-multiply})

Looks simpler and cleaner for me.

On Wed, Jun 5, 2013 at 12:16 PM, john <john.vie...@gmail.com> wrote:
Hi,
I recently wrote some code for which I have 2 alternative implementations.
So what I did is write a protocol:

(defprotocol Calculator
      (calc-add [this data])
(calc-multiply [this data]))


I then created two namespaces for my two implementations:
which each had a function:

(defn make-calculator []
   (reify Calculator
     (calc-add [this data] .....)
(calc-multiply [this data]....))

So my core code was using this protocol and I can switch  implementation by
just handing my "protocol-using-code" a different make-calculator.

But am I really doing programming in a functional style?

I mean I am creating with reify a class only so that my different
implementation gets called.
This "reify" makes me think "this is not functional but more OO like".

On the other hand it is very nice to have a "grouping of certain functions"
and it makes it clear this protocol
is a plugin point for custom implementations.

I don't know?! Am I just complaining about perfect readable side effect free
code?

Many Greetings
John

--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to