Hi Thomas, binding - really? :-). Apart from the general negative reaction they 
seem to have, I don’t want the individual elements (e.g. text and number) to 
assume rely on the binding as they can be called individually as well and the 
binding would just get in the way.

My understanding is that if I want to change a call to a function _before_ that 
call happens then my only option is to use a macro?

(I also realise this use-case will never need a macro as hiccup very sensibly 
uses data so the thing passed to (form) is simply a vector.)

I am saying, the discussion of whether _this example_ justifies a macro is mute 
- I agree it doesn’t.

> On 2 Oct 2015, at 15:01, Thomas Heller <th.hel...@gmail.com> wrote:
> 
> 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 
>> <http://gmail.com/>> 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 
>> <http://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+u...@ <>googlegroups.com <http://googlegroups.com/>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en 
>> <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 <http://googlegroups.com/>.
>> For more options, visit https://groups.google.com/d/optout 
>> <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 
> <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 
> <mailto:clojure+unsubscr...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout 
> <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.

Reply via email to