This is my first venture into macros since starting with Clojure a bunch of 
years ago - no urge here. I also use binding for a use-case I haven’t seen any 
other solution for; an implementation of a protocol which doesn’t take a tx as 
a parameter but wants to participate in a tx. Binding is a perfect fit for that.

I think we agree entirely and I think I maybe misled with the use-case I was 
apparently proposing using a macro for :-). My question was more about _how_ do 
I get this to work rather than _should_ I do it this way.

Thanks again Thomas.

> On 2 Oct 2015, at 15:48, Thomas Heller <th.hel...@gmail.com> wrote:
> 
> Well, yeah .. don't use binding. Sometimes they are a good solution though, 
> so don't forget about it.
> 
> Again I do not know your future plans. I would always recommend writing 
> everything with data+functions first. If you find that you have written the 
> same thing over and over again it might be time to introduce a new function 
> OR actually a macro if that doesn't work.
> 
> Macros sure are extremely powerful, so figuring out exactly when to use them 
> is quite hard. I know that it took me quite some time to get rid of the "hey, 
> just use a macro" urge.
> 
> Anyways, glad we agree that your initial macro does not need to exist. ;)
> 
> cheer,
> /thomas
> 
> On Friday, October 2, 2015 at 4:15:47 PM UTC+2, Colin Yates wrote:
> 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.h...@gmail.com <javascript:>> 
>> 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 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 
>> <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 
>> <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