-
-
Save stephendeyoung/7720578 to your computer and use it in GitHub Desktop.
(defn actions [array-of-funcs] | |
(doseq [func array-of-funcs] (func))) |
(defn show-dropdown [e] | |
(this-as button | |
(let [$button (js/$ button)] | |
(.preventDefault e) | |
(remove-dropdown) | |
(.addClass (.parents $button ".dropdown") "open")))) |
(defn show-dropdown [e] | |
(this-as button | |
(let [$button (js/$ button)] | |
(actions | |
(array (fn [] (.preventDefault e)) | |
(fn [] (remove-dropdown)) | |
(fn [] (.addClass (.parents $button ".dropdown") "open"))))))) |
Good point @mullr, I think I understood the original posters code being that he wanted to do all the mutations in a separate function keeping the other functions as pure as possible but then again this notion of pure is probably not inline with the functional notion of pure. While I like the idea, your post has given me a time to reflect and I'm not sure how best to solve this, but I do like delegating the mutation to a single function thereby keeping the other functions pretty clean. I haven't implemented this in my own app just yet, perhaps I'll wait to see if a more clean approach surfaces during my own development.
Sorry for the delayed response. Thanks for your comments @frankhale and @mullr.
@mullr the reason I feel my pure implementation is pure is because there are no side effects in the show-dropdown
function. The side effects (preventing the default action, adding a class etc) are handled by the doseq
expression. I thought this might be a slightly cleaner way of doing things.
Unless I've misunderstood your implementation you have side effects in your prevent-default!
and add-dropdown-class!
functions because you have two statements: one to change state and then another to set the return value of the function.
However, as you've suggested I'm not sure what this approach really buys you. I was interested in how you could write more functional code in CLJS than JS but I've found that you still end up having a lot of side effects in CLJS (mainly because of the DOM API). I thought you could hide this ugliness in my actions
function but, to be honest, you could implement something like this in JS anyway.
I don't see how this is any more pure than the original. There's a layer of indirection in there, but what does it buy you?
A functional approach to this problem may be: take a DOM value as input and generate a modified value as output. Unfortunately I don't know how to do DOM-as-a-value. I suppose you could string them together in the same way though:
I'm not sure I like this approach overall. It has the advantage of being explicit about when state is being mutated, and of using a somewhat more idiomatic way of stringing functions together. This is how I would do it if I did have DOM-as-a-value. But the individual handlers are somewhat bulky, and it's somewhat more code than the original version.
If I was reading someone else's code, I would be happiest to see your original 'impure' version, perhaps with a "!" at the end of the function name.