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

Reply via email to