Piping data through arbitrary functions in Clojure

前端 未结 3 1950
长发绾君心
长发绾君心 2021-01-07 22:10

I know that the -> form can be used to pass the results of one function result to another:

(f1 (f2 (f3 x))) 
(-> x f3 f2 f1) ; equivalent          


        
相关标签:
3条回答
  • 2021-01-07 22:57

    I must admit I'm really new to clojure and I might be missing the point here completely, but can't this just be done using comp and apply?

    user> (defn fn1 [x] (+ 2 x))
    user> (defn fn2 [x] (/ x 3))
    user> (defn fn3 [x] (* 1.2 x))
    user> (defn pipe [initial-data my-functions] ((apply comp my-functions) initial-data))
    user> (pipe 2 [fn1 fn2 fn3])
    2.8
    
    0 讨论(0)
  • 2021-01-07 23:08

    You can do this with a plain old reduce:

    (defn pipe [x fs] (reduce (fn [acc f] (f acc)) x fs))
    

    That can be shortened to:

    (defn pipe [x fs] (reduce #(%2 %1) x fs))
    

    Used like this:

    user> (pipe [1 2 3] [#(conj % 77) rest reverse (partial map inc) vec])
    [78 4 3]
    
    0 讨论(0)
  • 2021-01-07 23:09

    If functions is a sequence of functions, you can reduce it using comp to get a composed function. At a REPL:

    user> (def functions (list #(* % 5) #(+ % 1) #(/ % 3)))
    #'user/my-list
    user> ((reduce comp functions) 9)
    20
    

    apply also works in this case because comp takes a variable number of arguments:

    user> (def functions (list #(* % 5) #(+ % 1) #(/ % 3)))
    #'user/my-list
    user> ((apply comp functions) 9)
    20
    
    0 讨论(0)
提交回复
热议问题