Fork me on GitHub
#clojure
<
2015-10-07
>
ljosa16:10:40

Is there already a core function that does this?

(defn when* [f]
  #(when %
     (f %)))

(map (when* count) [nil "foo" nil "quux"])
=> (nil 3 nil 4)

pbostrom16:10:45

I would probably just write (map #(and % (count %)) [nil "foo" nil "quux"])

spei17:10:40

@ljosa why not (count (remove nil? coll))

ljosa17:10:40

@spei: count is just an example, of course. my code needs to do something on each of the elements of the input collection, but that thing can only be done if the elements are valid. then it needs to return the results in the same order as the input, with nil for invalid inputs.

ghadi17:10:38

not exactly what you need, but related

ljosa17:10:06

@ghadi: yeah, definitely related. maybe fwhen would be a better name for my utility function.

ghadi17:10:03

its operating assumption is to change the source data to a zero value, rather than changing the function

ljosa17:10:30

without going into too much detail, I have this:

(defn get-scored-intent [component psn urls]
  (->> (map #(when-not (intent-blacklisted? %) %) urls)
       (map (when* (partial tag-intent psn)))
       (map (when* p/make-raw-json-document))
       (#(p/multi-get (:intent-bucket component) % :timeout 500))
       (map (when* p/content))))

ljosa17:10:35

so blacklisted URLs are replaced with nil, and the rest of the stuff passes the nil through.

akiva17:10:37

Are you just wanting to apply a function to entries in a collection if a predicate returns true? This all seems rather complex for such a simple use case. Have a defn that contains the predicate and use it in the anonymous function in the map.

spei17:10:57

i agree because your functions look almost exactly like the way you would write them with normal "when" anyway

spei17:10:13

also, how do you guys get that cool clojure highlighting for keywords?

akiva17:10:34

@spei: Single backticks for inline, treble backticks for a quotebox.

ljosa17:10:38

when* just makes it a little less messy. (map (when* p/make-raw-json-document)) instead of (map #(when % (p/make-raw-json-document %))). I agree that it's maybe not worth it when there is not already a when* or fwhen or something like that.

spei17:10:32

@akiva thanks. @ljosa I would've written it about the same way but the anonymous function in map would've been (fn [x] (when x (f x)), which doesn't look bad. perhaps refactoring your functions to include a check is better.

akiva17:10:34

@ljosa: Yeah, I can see that. But it’s one of those things where if it aids in clarity, it might be worth the extra abstraction.

akiva17:10:08

And, on top of that, it’s also an issue of not spinning off a verb if it’s not used a lot. Otherwise, an anonymous function or a letfn might be better. Otherwise, everyone’s going to have to look to see the difference between when* and when.

spei17:10:16

(defn make-raw-json-doc [x]
        (when x (do-something x)) 
then your map function is just
(map make-raw-json-doc coll)

akiva17:10:41

Yeah, that’s what I was thinking.

akiva17:10:42

You could take it one level up by making a flexible higher-order function (such as a when* or do-if) but then def a partial or comp around it to give it a specific name like make-raw-json-doc that wraps a predicate and action.

ljosa17:10:10

thanks for input

akiva17:10:44

My pleasure.