murtaza52
murtaza52

Reputation: 47431

a better clojure idiom for mapping a seq of fns to an input

I have been coming across this pattern a lot in my code (map #(% a) fns) where a is a variable say a string and fns is a seq of fns like [count #(split ",")]. Is there a more concise way to express this pattern ?

Upvotes: 3

Views: 154

Answers (4)

georgek
georgek

Reputation: 877

I think the thrush operators are called for here.

user=> (-> "a b c d" 
       .toUpperCase 
       (.replace "A" "X") 
       (.split " ") 
       first)
"X"

http://clojuredocs.org/clojure_core/clojure.core/-%3E

http://clojuredocs.org/clojure_core/clojure.core/-%3E%3E

Upvotes: 0

Ankur
Ankur

Reputation: 33657

The pattern is already concise. But if you want to create an abstraction which represent a function collection and is also callable, you can try something like this:

(defmacro function-coll [param-count]
  (let [params (repeatedly param-count gensym)
        name (symbol (str "Functions-" param-count))]
    `(deftype ~name [fns#]
       clojure.lang.IFn
       (invoke [_ ~@params] (map #(% ~@params) fns#)))))


(function-coll 1)
(def one-fns (->Functions-1 [inc dec]))
(one-fns 10)

(function-coll 2)
(def two-fns (->Functions-2 [str vector]))
(two-fns :hello :world)

Upvotes: 0

Rafał Dowgird
Rafał Dowgird

Reputation: 45131

A straightforward way to express it: (for [f fns] (f a))

Added only for completeness, it's as good as the map-based expression, unless you like for more than anonymous functions.

Upvotes: 1

A. Webb
A. Webb

Reputation: 26446

More concise? Probably not. Better idiom? Depends. juxt will take any number of fns as arguments and provide a function that is their juxtaposition. So, you could use it in place of your map like so

(def a "foo,bar,baz")

(map #(% a) [count #(split % #",")])
;=> (11 ["foo" "bar" "baz"])

((juxt count #(split % #",")) a)
;=> [11 ["foo" "bar" "baz"]]

On one hand, you have a lazy sequence of applications, on the other you have functional composition. Which is better depends on the need.

Upvotes: 3

Related Questions