Thanks for your responses. I'm glad to see that I'm not entirely on the wrong track here.
On Mon, May 11, 2009 at 6:39 PM, Sean Devlin <[email protected]> wrote: > > Okay, good point about approach #2. As I mentioned earlier, I'd use > approach #3 first. Here's how I'd write your macro as a function > > (defn process-feeds > [feeds body] > (body feeds)) > > And I'd call it like this > > (process-feeds (get-feeds-s-exp ...) (fn [feeds] body)) > > The first thing I'd like to mention is that this is VERY similar to > your with-feeds macro. I think your general approach is sound. > Following is simply my thoughts and opinions on avoiding a macro in > this case. > > I like this approach better because it segregates the calling from the > processing, and it lets you test each routine independently. Also, > forcing the second argument to be a function encourages defining the > function, which in turn encourages testing. I decided to go with the macro, because it makes the default scenario very convenient. The tests I write apply to the functions where the feeds operation is performed (and I have tests for the macro). When the need arises to have an explicitly defined and tested function, I can still use call-with-feeds without the macro. > Now, I've made an assumption, and that is the process-feeds has no > side effects. If you are doing something that is sequential, not > functional (like opening/closing a resource), then a macro makes > sense. > > My thoughts in a pithy sound-byte: > > If you are abstracting away a function, try to use a function. > If you are abstracting away a sequence, it's the right time to use a > macro. > > There are other classes of problems in the function-vs-macro debate, > and I we can save those for another day :) > > On May 11, 12:04 pm, Victor Rodriguez <[email protected]> wrote: >> On Mon, May 11, 2009 at 11:32 AM, Sean Devlin <[email protected]> >> wrote: >> >> > Here are my thoughts on the three approaches: >> >> > Approach #1: This seems the most straightforward. I'd write a >> > function that takes a map of conditions, and returns a list of >> > tuples. You can then do what you want with the list of tuples. >> >> > Approach #2: Remember the first rule of macro club: Don't write >> > macros if a function will do. From what you've described, this >> > application wraps a simple SELECT * FROM... , and a macro is overkill. >> >> Yes, you should not write a macro when a function will do, but I think >> you might be misinterpreting the "spirit" of the rule. >> >> Also, the "bottom-up" aspect of programming in Lisp should be kept in >> mind. In other words, you want to "write a language for solving your >> problem", and you should definitively use macros for that. >> >> So, if a "with-feeds" macro makes sense for the application, do write >> it! Just make sure the macro is simply syntax sugar for your >> functions. Following a pattern common in Scheme (at least), the >> implementation would run along the lines of: >> >> (defn call-with-feeds >> [f] >> "Call a function with the feeds as an argument" >> ...) >> >> (defmacro with-feeds >> [feeds & body] >> `(call-with-feeds (fn [~feeds] ~...@body))) >> >> Kind regards, >> >> Victor Rodriguez. >> >> > Approach #3: This is a good approach once you hit the limits of the >> > first approach, and before you move on to the second approach. >> >> > I've written SQL apps in Clojure too. And I've used approaches 1 and >> > 3. I only use approach 2 when I really have to, and I try to have the >> > macro do as little as possible. >> >> > In summary, try approaches: >> >> > 1 -> 3 -> 2 >> >> > I'll try to throw some code on github this evening so you can see an >> > example of what I do, and you can decide if it's a good fit for your >> > application. >> >> > Sean >> >> > On May 11, 4:05 am, Janico Greifenberg <[email protected]> wrote: >> >> Hi, >> >> >> I'm writing an RSS-reader using compojure and clojure.contrib.sql. As >> >> this is my first project in a functional language, I'm not sure about >> >> how to design the application. The concrete question I'm having right >> >> now, is how to encapsulate database queries in functions. For my >> >> RSS-reader, a basic operations is to display lists of feeds that I >> >> retrieve with the following code: >> >> >> (sql/with-connection db >> >> (sql/with-query-results >> >> feeds >> >> ["select id, title from feeds order by title"] >> >> >> As this happens at a few places in the code, I would like to >> >> encapsulate it somehow. I see several approaches to this, but I'm >> >> uncertain which of them is the most idiomatic way to do this in >> >> Clojure. >> >> >> (1) The straightforward approach seems to be a function that returns >> >> the feeds. However, I would have to call (doall feeds) to get the data >> >> out of the internals of contrib.sql/JDBC and into my application. So I >> >> guess this would not be the most efficient way. >> >> >> (2) Another idea is to create a function or macro with-feeds that >> >> wraps the query and creates a binding to be used inside the body. >> >> >> (3) Or I could have a function that takes another function as a >> >> parameter which gets called inside with-query-results and gets feeds >> >> as parameter. >> >> >> Which of these variants -- or another one that I did not think of -- >> >> would you recommend? >> >> >> Janico > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---
