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