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
Description: OpenPGP digital signature