Oh, right. (f m) instead of (apply f [m]). Duh.
On Wed, Apr 30, 2014 at 11:15 PM, Colin Fleming <colin.mailingl...@gmail.com > wrote: > I think it would because in that case you'd just pass your arg map > straight through rather than having to reconstruct it. So if you weren't > passed :y in g (in Mark's example), g wouldn't pass it on to f. By forcing > the reconstruction of the map from explicit args, you're forced to use the > value (incorrectly) destructured in g. Mark could work around it in his > example by using (apply f (mapcat identity m)) in g, but it's far from > intuitive. > > > On 1 May 2014 15:04, Jim Crossley <j...@crossleys.org> wrote: > >> Unless I'm missing something subtle, all of your points would hold if you >> removed the & in your argument vector to turn your kwargs into an explicit >> map, wouldn't they? One advantage is you'd be able to (apply f [m]), but >> I'm not sure the :or logic would be any less troublesome. >> >> >> On Wed, Apr 30, 2014 at 8:06 PM, Mark Engelberg <mark.engelb...@gmail.com >> > wrote: >> >>> Here's the thing I can't stand about keyword args: >>> >>> Let's start off with a simple function that looks for keys x and y, and >>> if either is missing, >>> replaces the value with 1 or 2 respectively. >>> >>> (defn f [& {:keys [x y] :or {x 1 y 2}}] >>> [x y]) >>> >>> => (f :x 10) >>> [10 2] >>> >>> So far, so good. >>> >>> Now, let's do an extremely simple test of composability. Let's define a >>> function g that destructures the keyword args, and if a certain keyword >>> :call-f is set, then we're just going to turn around and call f, passing >>> all the keyword args along to f. >>> >>> (defn g [& {call-f :call-f :as m}] >>> (when call-f >>> (apply f m))) >>> >>> => (g :call-f true :x 10) >>> [1 2] >>> >>> What? Oh right, you can't apply the function f to the map m. This >>> doesn't work. If we want to "apply" f, we somehow need to apply it to a >>> sequence of alternating keys and values, not a map. >>> >>> Take 2: >>> >>> (defn g [& {:keys [call-f x y] :as m}] >>> (when call-f >>> (f :x x :y y))) >>> >>> OK, so this time we try to workaround things by explicitly calling out >>> the names of all the keywords we want to capture and pass along. It's >>> ugly, and doesn't seem to scale well to situations where you have an >>> unknown but at first glance, it seems to work: >>> >>> => (g :call-f true :x 80 :y 20) >>> [80 20] >>> >>> Or does it? >>> >>> => (g :call-f true :x 10) >>> [10 nil] >>> >>> What is going on here? Why is the answer coming out that :y is nil, >>> when function f explicitly uses :or to have :y default to 2? >>> >>> The answer is that :or doesn't do what you think it does. The word "or" >>> implies that it substitutes the default value of :y any time the >>> destructured :y is nil or false. But that's not how it really works. It >>> doesn't destructure and then test against nil; instead the :or map only >>> kicks in when :y is actually missing as a key of the map. >>> >>> This means that in g, when we actively destructured :y, it got set to a >>> nil, and then that got passed along to f. f's :or map didn't kick in >>> because :y was set to nil, not absent. >>> >>> This is awful. You can't pass through keyword arguments to other >>> functions without explicitly destructuring them, and if you destructure >>> them and pass them along explicitly, nil values aren't picked up as absent >>> values, so the :or default maps don't work properly. >>> >>> To put it simply, keyword args are bad news for composability. >>> >>> It's a shame, and I'd love to see this improved (rather than just having >>> the community give up on keyword arguments). >>> >>> -- >>> 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. >>> >> >> -- >> 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. >> > > -- > 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. > -- 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.