[英]Clojure: compose functions of arity 2 (or higher)
我正在使用可變數量的函數處理數據,具體取決於參數。 每個處理功能都會從其前身接收數據,對其進行處理並將其傳遞給下一個功能。
(defn example [data]
(do-things-to data))
我的申請流程是
小樣:
(let [my-big-fun (reduce comp (filter identity) vector-of-functions)]
(wrapper lots-a-arguments big-fun)
現在我發現我不僅需要將數據傳遞給函數,還需要另一個數據集。
(defn new-fun-example [root data]
(do-things-to-both root data))
有沒有辦法做類似於我對 arity-1 函數所做的減少的事情? 簡單的juxt
行不通的,因為每個函數都會更改下一個需要的數據。 返回'(root data)
或類似的 seq 將需要在許多函數中進行大量重寫。
有任何想法嗎? 我想答案是“宏觀”,但我從來沒有擺弄過這些......
編輯1:
第二個參數是對不斷增長的圖形數據結構的引用,因此它不需要由函數處理,只需以某種方式傳遞即可。 但是這些函數可能來自不同的命名空間,所以我不能簡單地將根放在更高的范圍內來訪問它。 一個全球性的def
將是可能的,但極其丑陋...
當我寫這篇我只是想我會的功能映射到partial
不知何故,之前comp
荷蘭國際集團他們。
編輯2:
filter identity
引起了很多混亂,這不是我的問題的一部分。 我一開始就不應該把它包含在我的樣本中。 我按照敏捷的棕色狐狸的建議解決了任務,並為有時晦澀難懂而道歉。 最小解決方案示例:
(defn example [root data]
(swap! root + data))
(defn fn-chainer [vector-of-functions]
(let [the-root (atom 0)
; this filter step is just required to remove erroneously apperaring nils
; from the vector of functions - not part of the question
vector-of-functions (filter identity vector-of-functions)
; bake the atom to the functions
vector-of-functions (mapv #(partial % the-root) vector-of-functions)
; now chain each funcion's result as argument to the next one
my-big-fun (reduce comp vector-of-functions)]
; let the function chain process some dataset
(my-big-fun 5))
; test some function vectors
(fn-chainer [example])
=> 5 ; = 0 + 5
(fn-chainer [example example])
=> 10 ; = 0 + 5 +5
(fn-chainer [example nil example example nil nil])10
=> 20 ; = 0 + 5 + 5 + 5 + 5, nils removed
正如您在編輯中提到的,您確實可以將您的功能映射到具有root
烘焙功能的新功能:
(mapv #(partial % root) vector-of-functions)
首先,我覺得這里發生了很多事情:
(filter identity)
是一個轉換器,但沒有說其他 fns 返回轉換器或者包裝器是否需要轉換器,並且鑒於其中一些將接收兩個參數,我們可以安全地說它們不是轉換器。 您可能想要(partial filter identity)
或#(filter identity %)
。
為什么要使用(reduce comp (filter identity) vector-of-functions)
而不是(apply comp (cons (partial filter identity) vector-of-functions)
?
考慮到如何組合這些函數,其中一些函數接收了更多您已經擁有值的參數,您可以使用部分:
(let [root [1 2 3]
other-root [4 5 6]
vector-of-functions [(partial filter identity) example (partial my-fun-example root) (partial other-fun-example root other-root)]
my-big-fun (apply comp vector-of-functions)]
(wrapper lots-a-arguments big-fun))
編輯:我對上面的應用補償使用reverse
是錯誤的, (reduce comp [fn1 fn2 fn3])
將返回與應用時相同的結果(apply comp [fn1 fn2 fn3])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.