How to evaluate a sequence of impure functions in Clojure?

前端 未结 4 2066
没有蜡笔的小新
没有蜡笔的小新 2021-01-17 13:09

How can I evaluate a list of (impure) functions in Clojure? For instance:

[#(println \"1\") #(println \"2\") #(println \"3\")]

The expected

相关标签:
4条回答
  • 2021-01-17 13:44

    This will eagerly consume the whole seq, calling all functions for side effects and returning whatever the last one returns:

    (reduce #(%2) nil [#(println :foo) #(println :bar)])
    ; => prints :foo, then :bar, then returns nil
    

    If you want to hold onto the return values, you can use reductions instead:

    (reductions #(%2) nil [#(println :foo) #(println :bar)])
    ; => prints :foo, then :bar, then returns (nil nil)
    

    reductions is found in clojure.contrib.seq-utils in Clojure 1.1 and in clojure.core in current snapshots of 1.2.

    Update: Note that reductions returns a lazy seq, so it's no improvement over map (NB. in map you'd want to use #(%) rather than #(%2)). I mentioned it here mostly for completeness. In fact, I posted the whole answer for completeness, because normally I'd go with the doseq approach (see Brian's answer).

    0 讨论(0)
  • 2021-01-17 13:47

    (apply pcalls [#(println "1") #(println "2") #(println "3")]) does just that. Just be wary of pcalls' parallelism (therefore lack of sequentiality) and lazyness.

    0 讨论(0)
  • 2021-01-17 13:55
    user> (let [fs [#(println "1") #(println "2") #(println "3")]]
             (doseq [f fs] (f)))
    1
    2
    3
    nil
    
    0 讨论(0)
  • 2021-01-17 14:09

    An old question, I know, but there's another option. You could simply invoke the functions:

    (defn generate-fns [] 
       [#(println "1") #(println "2") #(println "3")]) 
    
    (dorun (pmap (memfn invoke) (generate-fns)))
    

    This allows you to decide in a different context how you would like to execute the functions (say, pmap, or claypoole's upmap for example)

    0 讨论(0)
提交回复
热议问题