Awesome!

I am still really a beginner with macros.  I had tried to get one to work,
but wasn't sure if it was possible.  Thanks!

On Fri, Jun 17, 2011 at 8:59 PM, Ken Wesson <kwess...@gmail.com> wrote:

> On Fri, Jun 17, 2011 at 7:32 PM, Alex Baranosky
> <alexander.barano...@gmail.com> wrote:
> > What is the best way to remove the duplication in these two functions?:
> >
> > (defn- next-day-of-week-in-future [day-num]
> >   (find-first #(= day-num (.. % dayOfWeek get))
> (today+all-future-dates)))
> >
> >
> > (defn- next-day-of-month-in-future [day-of-month]
> >
> >   (find-first #(= day-of-month (.. % dayOfMonth get))
> > (today+all-future-dates)))
> >
> >
> >
> > ;; Here (today+all-future-dates) is a seq of DateMidnight objects from
> joda
> > time
> >
> >
> > I tried to do something like this - but it failed due to my lack of
> > understanding:
> >
> > (defn- next-day-of-period [period day-of-period]
> >   (find-first #(= day-of-period (.. % period get))
> > (today+all-future-dates)))
> >
> > (def ^{:private true} next-day-of-week-in-future (partial
> next-day-of-period
> > 'dayOfWeek))
> >
> >
> > (def ^{:private true} next-day-of-month-in-future (partial
> > next-day-of-period 'dayOfMonth))
> >
> >
> >  No matching field found: period for class org.joda.time.DateMidnight
> >
> >
> > Is this kind of thing possible?  Are the interop macros or #() macro
> > interfering? I'd love to understand this bit a bit better.
>
> It's possible, but not the way you did it. Your problem is that
> dayOfMonth and dayOfWeek are Java methods rather than first-class
> functions.
>
> One possibility is to make your new function a macro; it will work
> then, by replacing "period" with dayOfMonth or dayOfWeek at
> macroexpansion time.
>
> The other is to replace the interop call (.. % period get) with (.get
> (period %)) and making two more functions:
>
> (defn day-of-month [x] (.dayOfMonth x))
>
> (defn day-of-week [x] (.dayOfWeek x))
>
> whereupon (next-day-of-period day-of-week foo) will work, for instance.
>
> The macro is probably preferable in this particular instance since it
> directly lets you plug in any valid period method name without having
> to write more wrapper functions like the above two for each one. Here
> it is:
>
> (defmacro next-day-of-period [period day-of-period]
>   `(find-first #(= ~day-of-period (.. % ~period get))
>    (today+all-future-dates)))
>
> => (macroexpand-1 '(next-day-of-period dayOfMonth 11))
> (user/find-first (fn* [p1__646__647__auto__] (clojure.core/= 11 (..
> p1__646__647__auto__ dayOfMonth clojure.core/get)))
> (user/today+all-future-dates))
>
> Don't worry about the clojure.core/get cruft. Clojure doesn't care
> about the namespace part of a symbol used in Java interop, only the
> name part. Observe:
>
> => (. (WeakReference. 42) clojure.core/get)
> 42
>
> Same result as with plain 'get. Heck,
>
> => (clojure.core/.get (WeakReference. 42))
> 42
>
> acts the same as plain (.get (WeakReference. 42))! Though
> (.clojure.core/get ...) blows up with a no such namespace exception.
>
> In fact:
>
> => (macroexpand-1 '(quux/.foo bar))
> (. bar foo)
>
> shows that (.foo bar) is transformed to (. bar foo) (and the namespace
> part of .foo, if any, dropped) by the macroexpander -- (.meth) symbols
> seem to be treated by the compiler as an open-ended set of implicit
> macros that expand to the (. bar foo) form of interop. Interestingly,
>
> => (macroexpand-1 '(. bar quux/foo))
> (. bar quux/foo)
>
> so macroexpansion isn't where the namespace gets stripped if it's
> already in (. bar foo) form; the compiled code must simply ignore
> everything but the name part of the symbol in the method name position
> (second argument to the dot special operator).
>
> --
> Protege: What is this seething mass of parentheses?!
> Master: Your father's Lisp REPL. This is the language of a true
> hacker. Not as clumsy or random as C++; a language for a more
> civilized age.
>
> --
> 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

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