Oh, right. (f m) instead of (apply f [m]). Duh.

On Wed, Apr 30, 2014 at 11:15 PM, Colin Fleming <colin.mailingl...@gmail.com
> wrote:

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

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to