Maybe something like this. Those calls polymorphic on the returrn
value of the anynimous function, so this is more powerful than
overloading.

(defmulti load-page (fn [p n] (:id p)))
(defmethod load-page :db [loader name] (println "db provider for page"
name))
(defmethod load-page :fs [loader name] (println "fs provider for page"
name))
(defmethod load-page :mock [loader name] (println "mock provider for
page" name))

The loader data structure has a field that identifies which provider
it has. The loader and providers may be records or maps:
(defrecord prov-rec [f1 f2 f3])
(defrecord loader-rec [id prov])

;; tests
(def loader (loader-rec. :mock (prov-rec. nil nil nil)))
(load-page loader "index.html")
;; real work
(def loader (loader-rec. :db (prov-rec. "data" "user" "pwd")))
(load-page loader "index.html")

Works with this one, too:
(def loader { :id :fs :prov { :user "root" :pwd "***"} } )


On Oct 14, 3:08 am, "Felix H. Dahlke" <f...@ubercode.de> wrote:
> Oh, I think I missed your suggestion of multimethods. They do in fact
> look pretty interesting, but I wasn't able to figure out how that would
> solve my problem - they look more like overloading than polymorphism to
> me. Would you mind posting a variant of my example that uses multimethods?
>
> On 14/10/10 04:28, Armando Blancas wrote:
>
>
>
> > One thing that OOP and FP can have in common is the use of
> > polymorphism. With protocols and types you can implement your Java
> > design efficiently because you'll get basically the same interfaces
> > and classes. The thing about hiding the calls to instances of a data
> > type is only to make the client code not reply on the interop
> > notation, even if it is only to call a method on them, just like
> > Clojure core functions do.
>
> > With multimethods you can have different versions of the same
> > function. You're right, you call it with the necessary data, one of
> > which will be the one that controls the dispatch. Both data types and
> > multimethods provide late-binding; the difference is that multi-
> > methods are objects turned inside-out, as if you keep a reference to
> > this (as a record with fields) and use in function calls. And each
> > method is a particular responsibility. That's how I think about it,
> > anyway.
>
> > Either choice should be fine. I write Java interfaces for
> > implementations in Clojure when I want interop with Java, otherwise I
> > use multimethods and do it all in Clojure.
>
> > On Oct 13, 1:37 pm, "Felix H. Dahlke" <f...@ubercode.de> wrote:
> >> I see. So instead of using interfaces and implementations of these, I
> >> would simply use closures, one for mock and one for production? That was
> >> actually my first attempt, but I didn't like it back then.
>
> >> Take this code for example - passing a function just to have it called
> >> feels weird:
>
> >> (defn load-page [provider name]
> >>   (provider name))
>
> >> (load-page (make-mock-provider) "home")
>
> >> In Java, this would probably look like this:
>
> >> class PageLoader {
> >>     Provider provider;
>
> >>     PageLoader(Provider p) {
> >>         provider = p;
> >>     }
>
> >>     Page loadPage(String name) {
> >>         provider.loadPage(name);
> >>     }
>
> >> }
>
> >> PageLoader l = new PageLoader(new MockProvider());
> >> l.loadPage("home");
>
> >> Then again, it might just feel weird because I've gotten very used to
> >> OOP. In my Java code, loading pages is a responsibility of the
> >> PageLoader and it delegates it to the Provider. Objects have
> >> responsibilities and send messages to each other to fulfill these,
> >> that's OOP.
>
> >> In functional programming, there's simply a function that has a certain
> >> functionality, and everything it needs to fulfill it has to be provided
> >> by the caller. That's at least how I understand it by now.
>
> >> Maybe I should just call the function returned by (make-mock-provider)
> >> directly? The interface in Java has the great benefit of ensuring type
> >> safety (plus there's no closures yet, so it's the only way), but does
> >> this make sense in a dynamic language? I mean, if I passed an
> >> implementation of the wrong interface or a closure with the wrong number
> >> of arguments, wouldn't both situations result in weird runtime errors?
>
> >> On 12/10/10 22:34, Armando Blancas wrote:
>
> >>>> Back to my question: Am I trying to do Java in Clojure? Is there a more
> >>>> Lisp-y way to do this?
>
> >>> You can hide the types so your client code is more lispy:
> >>> (defn load-page [prov] (.loadPage prov))
> >>> ;;test
> >>> (def mp (make-mock-provider)) ... (load-page mp)
> >>> ;;production
> >>> (def prov (make-provider)) ... (load-page prov)
>
> >>> Depending on your app the provider could be a singleton and need not
> >>> be passed to each function. Another option is multimethods, in which
> >>> case you'd be using mock functions with an argument that would
> >>> indicate which version to dispatch to.
>
> >>> As for the repl, I think it works just as well for bottom-up and top-
> >>> down development. I use it for both all the time and to avoid throw-
> >>> away tests I write them top-down, black-box for only what's visible to
> >>> client/interop code first, then move down the layers as the code is
> >>> more mature and stable. I'm not really into TDD but I depend on a test
> >>> suite as complete as I can get it.
>
> >>  signature.asc
> >> < 1KViewDownload
>
>
>
>  signature.asc
> < 1KViewDownload- Hide quoted text -
>
> - Show quoted text -

-- 
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

Reply via email to