2

我正在处理具有可变数量的函数的数据,具体取决于参数。每个处理功能都将从其前身接收数据,对其进行处理并将其传递给下一个功能。

(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) 或类似的序列将需要在许多函数中进行大量重写。

有任何想法吗?我想答案是“宏观”,但我从来没有摆弄过这些......

编辑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
4

2 回答 2

1

正如您在编辑中提到的那样,您确实可以将您的函数映射到新的函数root中:

(mapv #(partial % root) vector-of-functions)
于 2015-09-18T13:16:44.160 回答
0

首先,我觉得这里发生了很多事情:

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

于 2015-09-18T12:05:18.517 回答