簡體   English   中英

Clojure:組合 arity 2(或更高)的函數

[英]Clojure: compose functions of arity 2 (or higher)

我正在使用可變數量的函數處理數據,具體取決於參數。 每個處理功能都會從其前身接收數據,對其進行處理並將其傳遞給下一個功能。

(defn example [data]
  (do-things-to data))

我的申請流程是

  1. 檢查參數並將所需函數存儲在向量中
  2. 創建一個包含所有必要步驟的函數
  3. 調用一個包裝函數來進行文件管理並最終應用該函數

小樣:

(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)

首先,我覺得這里發生了很多事情:

  1. (filter identity)是一個轉換器,但沒有說其他 fns 返回轉換器或者包裝器是否需要轉換器,並且鑒於其中一些將接收兩個參數,我們可以安全地說它們不是轉換器。 您可能想要(partial filter identity)#(filter identity %)

  2. 為什么要使用(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM