Well, if you don't like that 'form' you could use a binding. (binding [form/*state* {:editing? true :values form-values :validation validation-report :on-change handle-form-change}] (form/tag (form/text :name) (form/number :age)))
Anyways, I would not recommend using the binding but doesn't mean you can't. I can't quite imagine what your future plans look like but you probably won't need a macro. ;) cheers, /thomas On Friday, October 2, 2015 at 3:34:48 PM UTC+2, Colin Yates wrote: > > Hi Thomas - yes, you are right. The example I provided is all pain/no-gain > in terms of macros. However, future plans will require manipulating the > invocation of (for example form/text and form/number) before they are > evaluated. > > Having said all of that, that repeated ‘form’ does bug me a bit :-). I do > absolutely agree that the cognitive overhead of the macro isn’t justified > here. > > On 2 Oct 2015, at 14:29, Thomas Heller <th.h...@gmail.com <javascript:>> > wrote: > > Have you tried NOT using a macro at all? This code does not need to be a > macro at all if you ask me. > > Just a little sketch but things could look just about the same without any > macros at all: > > (let [form {:editing? true > :values form-values > :validation validation-report > :on-change handle-form-change}] > (form/tag form > (form/text form :name) > (form/number form :age))) > > > ;; in-ns 'form > > (defn text [form field] > [text-component {:id field > :value (get-in form [:values field]) > ...}]) > > (defn tag > [{:keys [editing?] :as form} & children] > (into [:div.form.horizontal > {:class (if editing? "editing" "editable")}] > children)) > > > Use macros very sparingly, most of the time data and functions are just > better. > > Just my 2 cents, > /thomas > > On Wednesday, September 30, 2015 at 10:29:30 PM UTC+2, Colin Yates wrote: >> >> Hi all, >> >> I am banging my head against the wall - I think it is obvious but I have >> started too long: >> >> The use-case is that I want a form which takes a set of children. The >> form also takes in some form-wide state, like the form-wide validation, the >> values for each item etc. I want the macro, for each child, to decorate >> that child by extracting the validation errors and value from the form-wide >> state. >> >> So, assuming: >> - validation looks like {:name "Duplicate name" :age "You must be at >> least 0"} >> - form-values looks like {:name "a-duplicate-user" :age -1} >> >> then my form might look like: >> >> (form {:editing? true :values form-values :validation validation-report >> :on-change handle-form-change} >> [form/text {:id :name}] >> [form/number {:id :age}]) >> >> After the macro I want the following code: >> >> [:div.form.horizontal >> {:class "editing"} >> [form/text {:id :name :value "a-duplicate-user" :errors "Duplicate >> name" :on-click (fn [e] (handle-form-change :name (-> e .target .value])] >> [form/number {:id :age :value "-1" :errors "You must be at least 0" >> :on-click (fn [e] (handle-form-change :age (-> e .target .value))]] >> >> However, ideally the macro would _not_ emit the contents of the input as >> literals but would emit code that inspects the provided parameters at >> run-time (i.e. rather than :value "a-duplicate-user" I would much prefer >> :value (-> state values :name) as that will allow me to pass in an atom for >> example. >> >> I have tried so many variations and evaluating the state (e.g. (:editing? >> state)) works fine as the emitted code has the destructured values, but >> that doesn't work for an atom. >> >> Here is my attempt at trying to emit code that interrogates the provided >> parameter. >> >> (defmacro form [state & elements] >> (let [state# state] >> `[:div.form.horizontal >> {:class (if (:editing? state#) "editing" "editable")} >> ~@(map (fn [[_ {:keys [id]} :as child]] >> (update child 1 assoc >> :editing? (:editing? state#) >> :value `(-> (:values state#) 'deref (get ~id)) >> :on-change `(fn [e#] >> (js/console.log "E: " >> (cljs.core/clj->js e#)) >> ((:on-change state#) ~id (-> e# >> .-target .-value))))) >> elements)])) >> >> The error I am getting is that there is such var as the gen-sym's state# >> in the namespace. >> >> The generic thing I am trying to do is remove the boilerplate from each >> of the items in the form. >> >> Any and all suggestions are welcome. >> >> Thanks! >> > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clo...@googlegroups.com <javascript:> > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+u...@googlegroups.com <javascript:> > 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 unsubscribe from this group and stop receiving emails from it, send an > email to clojure+u...@googlegroups.com <javascript:>. > For more options, visit https://groups.google.com/d/optout. > > > -- 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 unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.