Re: Kwargs vs explicit parameter map for APIs?
In the blog post, tcrayford gives an example of the difficulties in wrapping a kwargs function: (defn my-wrapper [ kwargs] (let [options (assoc (apply hash-map kwargs) :my-default-arg 1)] (apply (your-api-fn (flatten (into '() options)) Sure, that's convoluted (and I couldn't actually get it to work on real code). But isn't this a much simpler way: (defn my-wrapper [ kwargs] (apply your-api-fn :my-default-arg 1 kwargs)) Am I overlooking something? On Mon, Mar 23, 2015 at 5:55 AM, tcrayford tcrayf...@gmail.com wrote: Hi there, I feel pretty strongly about this - I *much* prefer using APIs with explicit options maps. The community is pretty divided though. I wrote up the tradeoffs (which are well discussed here as well), as well as a list of libraries using each style: http://yellerapp.com/posts/2015-03-22-the-trouble-with-kwargs.html To me, typing two extra characters ain't a big deal, but unrolling/rolling up maps and not being able to manipulate options easily is a bunch of pain, so I always choose explicit maps wherever possible. On Tuesday, 17 March 2015 06:42:37 UTC+9, Leon Grapenthin wrote: Kwargs has clearly been designed for one purpose: A caller should have to type less. A simple rule to follow is to use kw args if the exposed thing is a function not expected to be used in functional composition or a certain DSLish kind of macro. If your exposed function will be used in functional composition more often than called in typed out code, with kwargs you are using the feature to its opposite purpose: People have to type even more. For an example, if your thing is called load-config-file! and is used in one or two places of code, use kwargs by all means. If your thing is called path-for and resolves an URL for a map of parameters, kwargs is a very unfortunate choice. On Saturday, April 26, 2014 at 12:41:22 AM UTC+2, 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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.
Re: Kwargs vs explicit parameter map for APIs?
Yep: that won't override the arg if the caller passes it to you as well. -- 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.
Re: Kwargs vs explicit parameter map for APIs?
That explains it. In the type of stuff I write, that possibility wouldn't arise: there is no calling code that I can't control, and I definitely want the ability to change my wrapper's default. In any case, I realized the reason your blog code didn't run was an error: you need to change (apply (your-api-fn ... to (apply your-api-fn ... On Sun, Apr 5, 2015 at 7:46 PM, tcrayford tcrayf...@gmail.com wrote: Yep: that won't override the arg if the caller passes it to you as well. -- 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.
Re: Kwargs vs explicit parameter map for APIs?
How come this is so debated, but normal variadic functions are not? Is it only because there's nothing equivalent to apply for kwarg functions? Would it really be such a huge addition to clojure.core to add a simple mapply function, especially given that the core API have kwarg functions? (this might not be the right forum to discuss language additions, but might be interesting to see if anyone else agrees) Den tisdag 24 mars 2015 kl. 01:25:51 UTC+1 skrev solussd: I believe the current behavior with apply is the correct behavior as a map can be treated as a sequence of MapEntrys. -- On Mar 23, 2015, at 19:15, Mark Engelberg mark.en...@gmail.com javascript: wrote: Yes, I thought that technique worked, but I just conducted the same experiment as you did and confirmed that it doesn't. I must have been misremembering. You are correct that passing a map to a keyword-arg function is more of a nuisance than it should be. On Mon, Mar 23, 2015 at 4:36 PM, Matching Socks phill...@gmail.com javascript: wrote: Could you give an example demonstrating this? user (defn a [ {x :x y :y}] (vector x y)) #'user/a user (a :y 7 :x 3) [3 7] user (apply a {:x 3 :y 7}) [nil nil] On Monday, March 23, 2015 at 6:13:55 AM UTC-4, puzzler wrote: It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. -- 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 --- 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. -- 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 --- 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. -- 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.
Re: Kwargs vs explicit parameter map for APIs?
I guess with mapply using kwarg defined functions in compositional context would be helpful. It would have to be implemented as a method of the function object itself so that the map can be passed directly without any transformation. On Tuesday, March 24, 2015 at 11:03:17 PM UTC+1, Marcus Magnusson wrote: How come this is so debated, but normal variadic functions are not? Is it only because there's nothing equivalent to apply for kwarg functions? Would it really be such a huge addition to clojure.core to add a simple mapply function, especially given that the core API have kwarg functions? (this might not be the right forum to discuss language additions, but might be interesting to see if anyone else agrees) Den tisdag 24 mars 2015 kl. 01:25:51 UTC+1 skrev solussd: I believe the current behavior with apply is the correct behavior as a map can be treated as a sequence of MapEntrys. -- On Mar 23, 2015, at 19:15, Mark Engelberg mark.en...@gmail.com wrote: Yes, I thought that technique worked, but I just conducted the same experiment as you did and confirmed that it doesn't. I must have been misremembering. You are correct that passing a map to a keyword-arg function is more of a nuisance than it should be. On Mon, Mar 23, 2015 at 4:36 PM, Matching Socks phill...@gmail.com wrote: Could you give an example demonstrating this? user (defn a [ {x :x y :y}] (vector x y)) #'user/a user (a :y 7 :x 3) [3 7] user (apply a {:x 3 :y 7}) [nil nil] On Monday, March 23, 2015 at 6:13:55 AM UTC-4, puzzler wrote: It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. -- 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 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 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+u...@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 clo...@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 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+u...@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.
Re: Kwargs vs explicit parameter map for APIs?
Ha! I just noticed that this thread was started a year ago, and I posted a similar comment back then. Well, at least I'm consistent :) On Mon, Mar 23, 2015 at 3:13 AM, Mark Engelberg mark.engelb...@gmail.com wrote: Your article makes things a little more complicated than they need to be -- there is a special destructuring syntax in Clojure for pouring keyword args directly into a map (just do the map destructuring after the ). Also, I don't think you need to flatten the map of keyword args before calling apply. It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. Despite that, I agree with you that keyword arg functions don't compose as well. If I'm remembering correctly, I think the biggest problem I ran into is that the :or destructuring technique for supplying default values only uses the default values if the specified keys are *missing* from the keyword args (as opposed to using the default values if the keyword args are set to nil). This became a problem when I'd destructure in one function (which would bind missing keys to nil) and then pass along the keywords to the next function. The missing keywords weren't treated as missing, and so the default values weren't supplied. It's been a while since I've needed to do this, so I apologize in advance if I'm inadvertently passing along some misinformation here. On Mon, Mar 23, 2015 at 2:55 AM, tcrayford tcrayf...@gmail.com wrote: Hi there, I feel pretty strongly about this - I *much* prefer using APIs with explicit options maps. The community is pretty divided though. I wrote up the tradeoffs (which are well discussed here as well), as well as a list of libraries using each style: http://yellerapp.com/posts/2015-03-22-the-trouble-with-kwargs.html To me, typing two extra characters ain't a big deal, but unrolling/rolling up maps and not being able to manipulate options easily is a bunch of pain, so I always choose explicit maps wherever possible. On Tuesday, 17 March 2015 06:42:37 UTC+9, Leon Grapenthin wrote: Kwargs has clearly been designed for one purpose: A caller should have to type less. A simple rule to follow is to use kw args if the exposed thing is a function not expected to be used in functional composition or a certain DSLish kind of macro. If your exposed function will be used in functional composition more often than called in typed out code, with kwargs you are using the feature to its opposite purpose: People have to type even more. For an example, if your thing is called load-config-file! and is used in one or two places of code, use kwargs by all means. If your thing is called path-for and resolves an URL for a map of parameters, kwargs is a very unfortunate choice. On Saturday, April 26, 2014 at 12:41:22 AM UTC+2, 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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
Re: Kwargs vs explicit parameter map for APIs?
Hi there, I feel pretty strongly about this - I *much* prefer using APIs with explicit options maps. The community is pretty divided though. I wrote up the tradeoffs (which are well discussed here as well), as well as a list of libraries using each style: http://yellerapp.com/posts/2015-03-22-the-trouble-with-kwargs.html To me, typing two extra characters ain't a big deal, but unrolling/rolling up maps and not being able to manipulate options easily is a bunch of pain, so I always choose explicit maps wherever possible. On Tuesday, 17 March 2015 06:42:37 UTC+9, Leon Grapenthin wrote: Kwargs has clearly been designed for one purpose: A caller should have to type less. A simple rule to follow is to use kw args if the exposed thing is a function not expected to be used in functional composition or a certain DSLish kind of macro. If your exposed function will be used in functional composition more often than called in typed out code, with kwargs you are using the feature to its opposite purpose: People have to type even more. For an example, if your thing is called load-config-file! and is used in one or two places of code, use kwargs by all means. If your thing is called path-for and resolves an URL for a map of parameters, kwargs is a very unfortunate choice. On Saturday, April 26, 2014 at 12:41:22 AM UTC+2, 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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.
Re: Kwargs vs explicit parameter map for APIs?
If there are enough optional args that they need to be named then I choose a map, every time. That said, I do must multi-arity fns quite a bunch as well (with the options map going on the end if applicable). I also depend quite heavily on prismatic's schema, and to a lesser extent core.typed and I am not sure how charges fit in with either of those, although I haven't tried. +1 for maps. On 23 March 2015 at 09:55, tcrayford tcrayf...@gmail.com wrote: Hi there, I feel pretty strongly about this - I *much* prefer using APIs with explicit options maps. The community is pretty divided though. I wrote up the tradeoffs (which are well discussed here as well), as well as a list of libraries using each style: http://yellerapp.com/posts/2015-03-22-the-trouble-with-kwargs.html To me, typing two extra characters ain't a big deal, but unrolling/rolling up maps and not being able to manipulate options easily is a bunch of pain, so I always choose explicit maps wherever possible. On Tuesday, 17 March 2015 06:42:37 UTC+9, Leon Grapenthin wrote: Kwargs has clearly been designed for one purpose: A caller should have to type less. A simple rule to follow is to use kw args if the exposed thing is a function not expected to be used in functional composition or a certain DSLish kind of macro. If your exposed function will be used in functional composition more often than called in typed out code, with kwargs you are using the feature to its opposite purpose: People have to type even more. For an example, if your thing is called load-config-file! and is used in one or two places of code, use kwargs by all means. If your thing is called path-for and resolves an URL for a map of parameters, kwargs is a very unfortunate choice. On Saturday, April 26, 2014 at 12:41:22 AM UTC+2, 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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: 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. 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.
Re: Kwargs vs explicit parameter map for APIs?
Your article makes things a little more complicated than they need to be -- there is a special destructuring syntax in Clojure for pouring keyword args directly into a map (just do the map destructuring after the ). Also, I don't think you need to flatten the map of keyword args before calling apply. It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. Despite that, I agree with you that keyword arg functions don't compose as well. If I'm remembering correctly, I think the biggest problem I ran into is that the :or destructuring technique for supplying default values only uses the default values if the specified keys are *missing* from the keyword args (as opposed to using the default values if the keyword args are set to nil). This became a problem when I'd destructure in one function (which would bind missing keys to nil) and then pass along the keywords to the next function. The missing keywords weren't treated as missing, and so the default values weren't supplied. It's been a while since I've needed to do this, so I apologize in advance if I'm inadvertently passing along some misinformation here. On Mon, Mar 23, 2015 at 2:55 AM, tcrayford tcrayf...@gmail.com wrote: Hi there, I feel pretty strongly about this - I *much* prefer using APIs with explicit options maps. The community is pretty divided though. I wrote up the tradeoffs (which are well discussed here as well), as well as a list of libraries using each style: http://yellerapp.com/posts/2015-03-22-the-trouble-with-kwargs.html To me, typing two extra characters ain't a big deal, but unrolling/rolling up maps and not being able to manipulate options easily is a bunch of pain, so I always choose explicit maps wherever possible. On Tuesday, 17 March 2015 06:42:37 UTC+9, Leon Grapenthin wrote: Kwargs has clearly been designed for one purpose: A caller should have to type less. A simple rule to follow is to use kw args if the exposed thing is a function not expected to be used in functional composition or a certain DSLish kind of macro. If your exposed function will be used in functional composition more often than called in typed out code, with kwargs you are using the feature to its opposite purpose: People have to type even more. For an example, if your thing is called load-config-file! and is used in one or two places of code, use kwargs by all means. If your thing is called path-for and resolves an URL for a map of parameters, kwargs is a very unfortunate choice. On Saturday, April 26, 2014 at 12:41:22 AM UTC+2, 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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
Re: Kwargs vs explicit parameter map for APIs?
I believe the current behavior with apply is the correct behavior as a map can be treated as a sequence of MapEntrys. -- On Mar 23, 2015, at 19:15, Mark Engelberg mark.engelb...@gmail.com wrote: Yes, I thought that technique worked, but I just conducted the same experiment as you did and confirmed that it doesn't. I must have been misremembering. You are correct that passing a map to a keyword-arg function is more of a nuisance than it should be. On Mon, Mar 23, 2015 at 4:36 PM, Matching Socks phill.w...@gmail.com wrote: Could you give an example demonstrating this? user (defn a [ {x :x y :y}] (vector x y)) #'user/a user (a :y 7 :x 3) [3 7] user (apply a {:x 3 :y 7}) [nil nil] On Monday, March 23, 2015 at 6:13:55 AM UTC-4, puzzler wrote: It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Could you give an example demonstrating this? user (defn a [ {x :x y :y}] (vector x y)) #'user/a user (a :y 7 :x 3) [3 7] user (apply a {:x 3 :y 7}) [nil nil] On Monday, March 23, 2015 at 6:13:55 AM UTC-4, puzzler wrote: It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Yes, I thought that technique worked, but I just conducted the same experiment as you did and confirmed that it doesn't. I must have been misremembering. You are correct that passing a map to a keyword-arg function is more of a nuisance than it should be. On Mon, Mar 23, 2015 at 4:36 PM, Matching Socks phill.w...@gmail.com wrote: Could you give an example demonstrating this? user (defn a [ {x :x y :y}] (vector x y)) #'user/a user (a :y 7 :x 3) [3 7] user (apply a {:x 3 :y 7}) [nil nil] On Monday, March 23, 2015 at 6:13:55 AM UTC-4, puzzler wrote: It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. -- 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.
Re: Kwargs vs explicit parameter map for APIs?
On 23 March 2015 at 10:13, Mark Engelberg mark.engelb...@gmail.com wrote: It's been a while since I've tested this, but I believe that if a map is passed as the last argument to apply, Clojure does the right thing and passes the map in as keyword args. I'm afraid not. Not even in the latest Clojure 1.7.0 alpha. - James -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Kwargs has clearly been designed for one purpose: A caller should have to type less. A simple rule to follow is to use kw args if the exposed thing is a function not expected to be used in functional composition or a certain DSLish kind of macro. If your exposed function will be used in functional composition more often than called in typed out code, with kwargs you are using the feature to its opposite purpose: People have to type even more. For an example, if your thing is called load-config-file! and is used in one or two places of code, use kwargs by all means. If your thing is called path-for and resolves an URL for a map of parameters, kwargs is a very unfortunate choice. On Saturday, April 26, 2014 at 12:41:22 AM UTC+2, 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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.
Re: Kwargs vs explicit parameter map for APIs?
or a macro (defmacro defkargs [name destrt body] `(clojure.core/defn ~name ([] (~name {})) ([a# b# {:as r#}] (~name (clojure.core/assoc r# a# b#))) ([~destrt] ~@body))) (defkargs kargs-test {:keys [some me]} (when (and some me) (+ some me))) (and (= (kargs-test :some 1 :me 2) (kargs-test {:some 1 :me 2}) 3) (= (kargs-test) nil)) On Friday, March 13, 2015 at 1:46:08 PM UTC-4, Dylan Butman wrote: Late chime in...how about both? (defn kargs ([] (kargs {})) ([a b {:as r}] (kargs (assoc r a b))) ([a] a)) On Thursday, May 1, 2014 at 12:21:03 AM UTC-4, Jim Crossley wrote: Oh, right. (f m) instead of (apply f [m]). Duh. On Wed, Apr 30, 2014 at 11:15 PM, Colin Fleming colin.ma...@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.en...@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 clo...@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 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+u...@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 clo...@googlegroups.com Note that posts from new
Re: Kwargs vs explicit parameter map for APIs?
Late chime in...how about both? (defn kargs ([] (kargs {})) ([a b {:as r}] (kargs (assoc r a b))) ([a] a)) On Thursday, May 1, 2014 at 12:21:03 AM UTC-4, Jim Crossley wrote: Oh, right. (f m) instead of (apply f [m]). Duh. On Wed, Apr 30, 2014 at 11:15 PM, Colin Fleming colin.ma...@gmail.com javascript: 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 javascript: 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.en...@gmail.com javascript: 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 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 --- 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. -- 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 --- You received this message because you are subscribed to the Google Groups Clojure group. To unsubscribe from this group and stop receiving
Re: Kwargs vs explicit parameter map for APIs?
After posting this last week I decided to go down the explicit map route, and I'm already really glad I did. Amongst other things, it has allowed me to have two similar calls easily share their common options and merge in the differences. I'm generally a fan of maintaining fairly minimal APIs, I don't think I'll be duplicating functions, I don't really see a need - two extra braces are just not that much noise for me. I'd rather use Alex's last example with the optional map arg than have my-function and my-function-from-map everywhere. On 30 April 2014 17:55, James Reeves ja...@booleanknot.com wrote: On 30 April 2014 06:07, Alex Baranosky alexander.barano...@gmail.comwrote: I especially dislike that my non-kwarg fns no-longer can elegantly accept no options. Let me illustrate: (defn foo [ {:keys [a b]}] [a b]) (foo :a 1 :b 2) (foo) You could write: (defn foo [ [{:keys [a b]}]] [a b]) (foo {:a 1 :b 2}) (foo) - James -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Thanks James, that's a useful version to experiment with :) On Wed, Apr 30, 2014 at 12:04 AM, Colin Fleming colin.mailingl...@gmail.com wrote: After posting this last week I decided to go down the explicit map route, and I'm already really glad I did. Amongst other things, it has allowed me to have two similar calls easily share their common options and merge in the differences. I'm generally a fan of maintaining fairly minimal APIs, I don't think I'll be duplicating functions, I don't really see a need - two extra braces are just not that much noise for me. I'd rather use Alex's last example with the optional map arg than have my-function and my-function-from-map everywhere. On 30 April 2014 17:55, James Reeves ja...@booleanknot.com wrote: On 30 April 2014 06:07, Alex Baranosky alexander.barano...@gmail.comwrote: I especially dislike that my non-kwarg fns no-longer can elegantly accept no options. Let me illustrate: (defn foo [ {:keys [a b]}] [a b]) (foo :a 1 :b 2) (foo) You could write: (defn foo [ [{:keys [a b]}]] [a b]) (foo {:a 1 :b 2}) (foo) - James -- 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.
Re: Kwargs vs explicit parameter map for APIs?
my two cents: The extra readability to users when using keyword args also comes from the fact that a function's options are explicit in its signature. So during development, instead of having to look them up in the docs or in the code, my emacs mini-buffer simply shows them to me. Although I do agree with all the good reasons against keywords arguments, to me this is still the decisive reason to prefer them... Joachim Op woensdag 30 april 2014 05:41:29 UTC+2 schreef James Reeves: On 30 April 2014 03:54, Sean Corfield se...@corfield.org javascript:wrote: I still think the keyword argument approach is far more readable to _users_ -- 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.
Re: Kwargs vs explicit parameter map for APIs?
But that's only true for the variables which are explicitly destructured in the function definition, which in my experience many are not - they're often later picked out of an :as args argument, perhaps dependent on a combination of the parameters which are explicitly destructured. Seesaw never does this, for example. I think it's dangerous to rely on this rather than the documentation since it's often an incomplete view of what the function requires. Cheers, Colin On 30 April 2014 21:03, Joachim De Beule joachim.de.be...@gmail.com wrote: my two cents: The extra readability to users when using keyword args also comes from the fact that a function's options are explicit in its signature. So during development, instead of having to look them up in the docs or in the code, my emacs mini-buffer simply shows them to me. Although I do agree with all the good reasons against keywords arguments, to me this is still the decisive reason to prefer them... Joachim Op woensdag 30 april 2014 05:41:29 UTC+2 schreef James Reeves: On 30 April 2014 03:54, Sean Corfield se...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ -- 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.
Re: Kwargs vs explicit parameter map for APIs?
And thinking about it (after pressing send, of course), you'd get the same benefit from destructuring an explicit map in the function parameter anyway, wouldn't you? On 30 April 2014 22:11, Colin Fleming colin.mailingl...@gmail.com wrote: But that's only true for the variables which are explicitly destructured in the function definition, which in my experience many are not - they're often later picked out of an :as args argument, perhaps dependent on a combination of the parameters which are explicitly destructured. Seesaw never does this, for example. I think it's dangerous to rely on this rather than the documentation since it's often an incomplete view of what the function requires. Cheers, Colin On 30 April 2014 21:03, Joachim De Beule joachim.de.be...@gmail.comwrote: my two cents: The extra readability to users when using keyword args also comes from the fact that a function's options are explicit in its signature. So during development, instead of having to look them up in the docs or in the code, my emacs mini-buffer simply shows them to me. Although I do agree with all the good reasons against keywords arguments, to me this is still the decisive reason to prefer them... Joachim Op woensdag 30 april 2014 05:41:29 UTC+2 schreef James Reeves: On 30 April 2014 03:54, Sean Corfield se...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ -- 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.
Re: Kwargs vs explicit parameter map for APIs?
We used kwargs for options extensively in Immutant 1.x, and we're moving to explicit maps for Immutant 2.x, for the reasons cited above. It's not obvious to me why the bad release-sharks example on the coding standards page [1] is bad. Why should the optional config be the least variance argument? I had to look up laudable, btw. It's one of those good words that sounds bad. :) [1] http://dev.clojure.org/display/community/Library+Coding+Standards On Wed, Apr 30, 2014 at 6:14 AM, Colin Fleming colin.mailingl...@gmail.comwrote: And thinking about it (after pressing send, of course), you'd get the same benefit from destructuring an explicit map in the function parameter anyway, wouldn't you? On 30 April 2014 22:11, Colin Fleming colin.mailingl...@gmail.com wrote: But that's only true for the variables which are explicitly destructured in the function definition, which in my experience many are not - they're often later picked out of an :as args argument, perhaps dependent on a combination of the parameters which are explicitly destructured. Seesaw never does this, for example. I think it's dangerous to rely on this rather than the documentation since it's often an incomplete view of what the function requires. Cheers, Colin On 30 April 2014 21:03, Joachim De Beule joachim.de.be...@gmail.comwrote: my two cents: The extra readability to users when using keyword args also comes from the fact that a function's options are explicit in its signature. So during development, instead of having to look them up in the docs or in the code, my emacs mini-buffer simply shows them to me. Although I do agree with all the good reasons against keywords arguments, to me this is still the decisive reason to prefer them... Joachim Op woensdag 30 april 2014 05:41:29 UTC+2 schreef James Reeves: On 30 April 2014 03:54, Sean Corfield se...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Maybe they want config in the least variance argument so it can be partial'ed? On Wed, Apr 30, 2014 at 10:03 AM, Jim Crossley j...@crossleys.org wrote: We used kwargs for options extensively in Immutant 1.x, and we're moving to explicit maps for Immutant 2.x, for the reasons cited above. It's not obvious to me why the bad release-sharks example on the coding standards page [1] is bad. Why should the optional config be the least variance argument? I had to look up laudable, btw. It's one of those good words that sounds bad. :) [1] http://dev.clojure.org/display/community/Library+Coding+Standards On Wed, Apr 30, 2014 at 6:14 AM, Colin Fleming colin.mailingl...@gmail.com wrote: And thinking about it (after pressing send, of course), you'd get the same benefit from destructuring an explicit map in the function parameter anyway, wouldn't you? On 30 April 2014 22:11, Colin Fleming colin.mailingl...@gmail.comwrote: But that's only true for the variables which are explicitly destructured in the function definition, which in my experience many are not - they're often later picked out of an :as args argument, perhaps dependent on a combination of the parameters which are explicitly destructured. Seesaw never does this, for example. I think it's dangerous to rely on this rather than the documentation since it's often an incomplete view of what the function requires. Cheers, Colin On 30 April 2014 21:03, Joachim De Beule joachim.de.be...@gmail.comwrote: my two cents: The extra readability to users when using keyword args also comes from the fact that a function's options are explicit in its signature. So during development, instead of having to look them up in the docs or in the code, my emacs mini-buffer simply shows them to me. Although I do agree with all the good reasons against keywords arguments, to me this is still the decisive reason to prefer them... Joachim Op woensdag 30 april 2014 05:41:29 UTC+2 schreef James Reeves: On 30 April 2014 03:54, Sean Corfield se...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Granted, but the word bad seems harsh without any explanation, especially if the common usage is to pass an empty map. On Wed, Apr 30, 2014 at 11:18 AM, Alex Robbins alexander.j.robb...@gmail.com wrote: Maybe they want config in the least variance argument so it can be partial'ed? On Wed, Apr 30, 2014 at 10:03 AM, Jim Crossley j...@crossleys.org wrote: We used kwargs for options extensively in Immutant 1.x, and we're moving to explicit maps for Immutant 2.x, for the reasons cited above. It's not obvious to me why the bad release-sharks example on the coding standards page [1] is bad. Why should the optional config be the least variance argument? I had to look up laudable, btw. It's one of those good words that sounds bad. :) [1] http://dev.clojure.org/display/community/Library+Coding+Standards On Wed, Apr 30, 2014 at 6:14 AM, Colin Fleming colin.mailingl...@gmail.com wrote: And thinking about it (after pressing send, of course), you'd get the same benefit from destructuring an explicit map in the function parameter anyway, wouldn't you? On 30 April 2014 22:11, Colin Fleming colin.mailingl...@gmail.comwrote: But that's only true for the variables which are explicitly destructured in the function definition, which in my experience many are not - they're often later picked out of an :as args argument, perhaps dependent on a combination of the parameters which are explicitly destructured. Seesaw never does this, for example. I think it's dangerous to rely on this rather than the documentation since it's often an incomplete view of what the function requires. Cheers, Colin On 30 April 2014 21:03, Joachim De Beule joachim.de.be...@gmail.comwrote: my two cents: The extra readability to users when using keyword args also comes from the fact that a function's options are explicit in its signature. So during development, instead of having to look them up in the docs or in the code, my emacs mini-buffer simply shows them to me. Although I do agree with all the good reasons against keywords arguments, to me this is still the decisive reason to prefer them... Joachim Op woensdag 30 april 2014 05:41:29 UTC+2 schreef James Reeves: On 30 April 2014 03:54, Sean Corfield se...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ -- 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
Re: Kwargs vs explicit parameter map for APIs?
On Apr 30, 2014, at 8:03 AM, Jim Crossley j...@crossleys.org wrote: It's not obvious to me why the bad release-sharks example on the coding standards page [1] is bad. Why should the optional config be the least variance argument? I had to look up laudable, btw. It's one of those good words that sounds bad. :) [1] http://dev.clojure.org/display/community/Library+Coding+Standards Well, that's a very recent change. Stuart Halloway's version has been the standard for years. Reid made those changes only a few days ago - and I saw no discussion of the proposed changes so I'd like to hear from Cognitect's folks about this: is it a change of heart by Clojure/core or are they unaware of the change? Sean Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) signature.asc Description: Message signed with OpenPGP using GPGMail
Re: Kwargs vs explicit parameter map for APIs?
I think they're unaware of the change, as it resulted from a recent conversation on IRC that same day, where sentiment indicated that kwargs are generally more trouble than they're worth and there's still confusion around it. What started it: the example of keys-destructuring on a list in a let binding, very odd to explain. (let [{:keys [a b c]} '(:a 1 :b 2 :c 3)] [a b c]) [1 2 3] On Wed, Apr 30, 2014 at 5:53 PM, Sean Corfield s...@corfield.org wrote: On Apr 30, 2014, at 8:03 AM, Jim Crossley j...@crossleys.org wrote: It's not obvious to me why the bad release-sharks example on the coding standards page [1] is bad. Why should the optional config be the least variance argument? I had to look up laudable, btw. It's one of those good words that sounds bad. :) [1] http://dev.clojure.org/display/community/Library+Coding+Standards Well, that's a very recent change. Stuart Halloway's version has been the standard for years. Reid made those changes only a few days ago - and I saw no discussion of the proposed changes so I'd like to hear from Cognitect's folks about this: is it a change of heart by Clojure/core or are they unaware of the change? Sean Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) -- 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.
Re: Kwargs vs explicit parameter map for APIs?
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.
Re: Kwargs vs explicit parameter map for APIs?
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.comwrote: 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.
Re: Kwargs vs explicit parameter map for APIs?
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.comwrote: 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
Re: Kwargs vs explicit parameter map for APIs?
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
Re: Kwargs vs explicit parameter map for APIs?
Having worked through this for java.jdbc (and to a lesser extent for CongoMongo), I think that I would approach it slightly differently in future: Provide two functions: one taking a map, one taking keyword arguments; the latter delegating to the former via {:as opts} and then internal calls can easily use the map-based argument approach. One of the additional complexities in java.jdbc (as it stands today) is that several functions accept an arbitrary number of arguments, followed by optional keyword arguments as well, so several functions have to parse their argument lists at runtime. Simplifying that to use a sequence (of current arguments) followed by a map (of options) would make several things easier inside the library, removing a lot of apply calls, as well as providing an API that is more amenable to dynamic call construction... I still think the keyword argument approach is far more readable to _users_ - and it's also what was recommended in the Clojure Library Guidelines right up until a few days ago: http://dev.clojure.org/pages/viewpage.action?pageId=9142444 Reid McKenzie changed it on April 24th, completely reversing the previous recommendation from Unroll optional named arguments to Don't unroll optional named arguments - compare version 6 (from Stuart Halloway) with Reid's edits in versions 7-11: http://dev.clojure.org/pages/diffpagesbyversion.action?pageId=1573132selectedPageVersions=11selectedPageVersions=6 Sean On Apr 25, 2014, at 3:41 PM, Colin Fleming colin.mailingl...@gmail.com 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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: 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. 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. Sean Corfield -- (904) 302-SEAN An Architect's View -- http://corfield.org/ Perfection is the enemy of the good. -- Gustave Flaubert, French realist novelist (1821-1880) signature.asc Description: Message signed with OpenPGP using GPGMail
Re: Kwargs vs explicit parameter map for APIs?
On 30 April 2014 03:54, Sean Corfield s...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ Really? It's only an omission of two braces. While readability is subjective, I'm not sure how that can be considered to be *far* more readable. From a purely practical perspective, explicit maps are generally a lot easier to work with. To my mind the disadvantages of keyword arguments often outweigh the small presentational benefits they have. - James -- 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.
Re: Kwargs vs explicit parameter map for APIs?
I'm extremely internally torn regarding kwargs. I use them a lot; I know they hinder composability; but every time I go back to straight maps for these kinds of things I really don't like all the extra noise characters and go back to kwargs. I feel like I really should be using regular maps for all the good reasons listed, but in practice I don't. Honestly, I don't usually run into the composability issues too often, so I'm getting by ok with my indulgence in kwargs, I suppose. I especially dislike that my non-kwarg fns no-longer can elegantly accept no options. Let me illustrate: (defn foo [ {:keys [a b]}] [a b]) (foo :a 1 :b 2) (foo) (defn foo [{:keys [a b]}] [a b]) (foo {:a 1 :b 1}) (foo {}) ;; -- unpleasant to my eyes, let me reimplement foo (defn foo This is also pretty gross ([] (foo {})) ([{:keys [a b]}] [a b])) So, yeah, I'm pretty torn. I like the option of having kwargs for the outer API shell, and explicit option maps internally. I've played with that a little as well at work to some ok success. Alex On Tue, Apr 29, 2014 at 8:41 PM, James Reeves ja...@booleanknot.com wrote: On 30 April 2014 03:54, Sean Corfield s...@corfield.org wrote: I still think the keyword argument approach is far more readable to _users_ Really? It's only an omission of two braces. While readability is subjective, I'm not sure how that can be considered to be *far* more readable. From a purely practical perspective, explicit maps are generally a lot easier to work with. To my mind the disadvantages of keyword arguments often outweigh the small presentational benefits they have. - James -- 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.
Re: Kwargs vs explicit parameter map for APIs?
On 30 April 2014 06:07, Alex Baranosky alexander.barano...@gmail.comwrote: I especially dislike that my non-kwarg fns no-longer can elegantly accept no options. Let me illustrate: (defn foo [ {:keys [a b]}] [a b]) (foo :a 1 :b 2) (foo) You could write: (defn foo [ [{:keys [a b]}]] [a b]) (foo {:a 1 :b 2}) (foo) - James -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Thanks everyone - I was leaning towards maps and sounds like that's the preferred approach. On 26 April 2014 10:59, Gary Trakhman gary.trakh...@gmail.com wrote: If it's more than a few parameters, I prefer maps.. It enables the possibility of things like merge. On Fri, Apr 25, 2014 at 6:56 PM, Andrey Antukh n...@niwi.be wrote: Hi! I have the same doubt! However, At this time, I prefer use a explicit map instead keywords, because for me is much clear that using keywords. Andrey. 2014-04-26 0:41 GMT+02:00 Colin Fleming colin.mailingl...@gmail.com: 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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. -- Andrey Antukh - Андрей Антух - andrei.anto...@kaleidos.net / n...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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
Re: Kwargs vs explicit parameter map for APIs?
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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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.
Re: Kwargs vs explicit parameter map for APIs?
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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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
Kwargs vs explicit parameter map for APIs?
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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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.
Re: Kwargs vs explicit parameter map for APIs?
Hi! I have the same doubt! However, At this time, I prefer use a explicit map instead keywords, because for me is much clear that using keywords. Andrey. 2014-04-26 0:41 GMT+02:00 Colin Fleming colin.mailingl...@gmail.com: 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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. -- Andrey Antukh - Андрей Антух - andrei.anto...@kaleidos.net / n...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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.
Re: Kwargs vs explicit parameter map for APIs?
Seesaw looks nice, but in retrospect I would use explicit maps if I had it to do all over again for exactly the reasons you mention. These days, I always use explicit maps for options. Dave On Fri, Apr 25, 2014 at 3:56 PM, Andrey Antukh n...@niwi.be wrote: Hi! I have the same doubt! However, At this time, I prefer use a explicit map instead keywords, because for me is much clear that using keywords. Andrey. 2014-04-26 0:41 GMT+02:00 Colin Fleming colin.mailingl...@gmail.com: 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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. -- Andrey Antukh - Андрей Антух - andrei.anto...@kaleidos.net / n...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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.
Re: Kwargs vs explicit parameter map for APIs?
If it's more than a few parameters, I prefer maps.. It enables the possibility of things like merge. On Fri, Apr 25, 2014 at 6:56 PM, Andrey Antukh n...@niwi.be wrote: Hi! I have the same doubt! However, At this time, I prefer use a explicit map instead keywords, because for me is much clear that using keywords. Andrey. 2014-04-26 0:41 GMT+02:00 Colin Fleming colin.mailingl...@gmail.com: 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 :instancelist :description My description :implements (keys class-methods) :methods (calculate-my-methods)) Map: (class/create-class {:instancelist :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. -- Andrey Antukh - Андрей Антух - andrei.anto...@kaleidos.net / n...@niwi.be http://www.niwi.be http://www.niwi.be/page/about/ https://github.com/niwibe -- 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.