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. 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 <vict...@gmail.com> wrote: > On Mon, May 11, 2009 at 11:32 AM, Sean Devlin <francoisdev...@gmail.com> > 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 <jgre...@googlemail.com> 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 clojure@googlegroups.com 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 -~----------~----~----~----~------~----~------~--~---