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 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.

Reply via email to