Hi,

On 9 Mrz., 08:52, Andreas Kostler <andreas.koestler.le...@gmail.com>
wrote:

>>> (defn make-native-query [db str foo]
>>>             (. (proxy [ONativeSynchQuery]
>>>                    [db str foo]
>>>                    (filter [rec]
>>>                         (.. rec (field "location") (eq "Madrid") and (field 
>>> "name") (eq "Dhali") go))) run objs))
>
> Well, I don't want the symbols location, name, etc to be evaluated...e.g. I 
> couldn't use location if not in a macro, right?
> Secondly, the structure isn't quite as uniform. Like in the example above
> (.. rec (create-query [[location eq "Madrid"] and [name eq "Dhali"]])) should 
> expand to something like
>
> (.. rec (field "location") (eq "Madrid") and (field "name") (eq "Dhali"))
>
> Maybe I'm still missing something but I can't see how I could do that without 
> a macro...

You could use keywords.

(query rec [[:location :eq "Madrid"] :and [:name :eq "Dhali"]])

where query is defined as

(defmulti query (fn [_ [_ op _]] op))

(defmethod query :and
  [rec [lhs _ rhs]]
  (-> rec (query lhs) .and (query rhs)))

(defmethod query :eq
  [rec [lhs _ rhs]]
  (-> rec (.field (name lhs)) (.eq rhs)))

Then there is no need for a macro and you can extend things for other
operators like :neq, :or and the like. If you don't need this
extensibility you can even go with a single function and a case.

(defn query
  [rec [lhs op rhs]]
  (case op
    :and (-> rec (query lhs) .and (query rhs))
    :eq  (-> rec (.field (name lhs)) (.eq rhs))))

This should read pretty much like the API you have to use.

If you really need macros the above should easy to modify:

(defmacro query
  [rec [lhs op rhs]]
  (case op
    'and `(-> ~rec (query ~lhs) .and (query ~rhs))
    'eq  `(-> ~rec (.field ~(name lhs)) (.eq ~rhs))))

Not tested, though.

By using the .notation for methods you don't have to ~' quote things
in the macro. And by using -> instead of .. you can also use plain
Clojure functions and macros besides method calls.

You cannot write a macro which expands the way you want it to without
significant effort with code walking and a surrounding macro. Which is
not appropriate for this case, I think.

Hope this helps.

Sincerely
Meikel

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