Yes, that's the preferred way of accepting kwargs now, I think. But it's just prettier syntax around the same problem. Note that using this form doesn't accept an explicit map, I still have to place the params inline in the function invocation. If I have:
(defn test1 [& {:keys [param1 param2] :as args}] ...) (defn test2 [& {:keys [param1 param2] :as args}] ...) Then when I call, say, test1, I still do it like this: (test1 :param1 "some value" :param2 "some value") Which means that if I want to have param2 be optional based on some runtime value, there's really no other way to do it than: (if condition? (test1 :param1 "..." :param2 "...") (test1 :param1 "...")) With two parameters that might be ok, but with 10 it's basically impossible, and your only option is to pass nil for some parameters and handle that inside your function. And if I want to call test1 from test2 I have to do either: (defn test2 [& {:keys [param1 param2] :as args}] (test1 :param1 param1 :param2 param2)) or: (defn test2 [& {:keys [param1 param2] :as args}] (apply test1 (mapcat identity args))) The first again doesn't scale past 2 or 3 params, and doesn't allow you to deal with optional parameters. The second probably needs a bit of head scratching to figure out what it's even doing the first time you see it. Note that if I pass an explicit map, I can still use the destructuring forms above, just without the & symbol, and then I can just pass the args map around, merge it for default parameters, add/remove params etc, and everything is good. Cheers, Colin On 26 April 2014 22:03, Glen Mailer <glenja...@gmail.com> wrote: > While reading the clojure.java.jdbc code yesterday, I discovered to my > surprise that map destructuring can be used after an & in an arglist. > > This should give you all the described benefits of the two approaches you > mention > > ((fn [a & {:as d}] d) 1 :opt1 'blah :opt2 false) > > You can also do defaults using :or - although these defaults don't get > merged into the value of :as - so an explicit (merge) might be better. > > ((fn [a & {:keys [misc] :or {misc :misc-default} :as d}] [d misc]) 1 :opt1 > 'blah :opt2 false) > > Hope that makes sense! > > Glen > > > On Friday, 25 April 2014 23:41:22 UTC+1, Colin Fleming wrote: >> >> Hi all, >> >> I'm working on an API at the moment, and I'm balancing whether to use >> inline keyword args which I would destructure in the functions, or whether >> to just pass an explicit params map as the last parameter. Comparison of >> the two options in case I'm not explaining myself well: >> >> Kwargs: >> (class/create-class :instance list >> :description "My description" >> :implements (keys class-methods) >> :methods (calculate-my-methods)) >> >> Map: >> (class/create-class {:instance list >> :description "My description" >> :implements (keys class-methods) >> :methods (calculate-my-methods)}) >> >> A lot of APIs I've seen have favoured kwargs, and it undeniably makes for >> some pretty code - Seesaw is the best example I've seen here, the API is a >> thing of beauty. However it seems to me to have some issues: >> >> 1. If I want to delegate to another call from within an API function >> and use the same arguments, it's really awkward: (apply delegate >> (mapcat identity args)) or some similarly awful black juxt magic. Or >> of course writing out all the parameters again, but that's even worse. >> 2. It's more difficult to make parameters optional based on some >> runtime criteria since the params are baked into the function call. I >> guess >> this is usually dealt with by making the calls handle nil for a particular >> parameter. >> >> Both of these are much easier when passing an explicit map. Any >> preferences here, from either writing or using APIs like this? >> >> Cheers, >> >> Colin >> > -- > 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.