我有一个命名空间来实现这样的多方法:
(ns a)
(defmulti funca (fn [system data] system))
(defmethod funca :add-z
[system data]
(conj data {:z 26}))
我有一个实现不同多方法的第二个命名空间:
(ns b)
(defmulti funcb (fn [system data new-element] system))
(defmethod funcb :add-element
[system data new-element]
(conj data new-element))
我有一个第三个命名空间定义为
(ns c
(:require [a :refer [funca]]
[b :refer [funcb]]))
我想在命名空间 c 中创建一个方法,我可以调用它
,例如(funcc (funca :add-z {:a 1 :b 2 :c 3})
(funcb :add-element {:y 25}))
这应该获取(funca :add-z {:a 1 :b 2 :c 3})
的结果(这将是{:a 1 :b 2 :c 3 :z 26}
的(,并将该结果用作(funcb :add-y-and-count-elements {:y 25})
的输入,然后返回结果{:a 1 :b 2 :c 3 :y 25 :z 26}
。
在尝试定义funcc
时,我正在尝试诸如
(ns c
(:require [a :refer [funca]]
[b :refer [funcb]]))
(defn funcc [funca funcb]
(partial funcb funca))
或
(defn funcc [funca funcb]
(funcb (funca)))
或
(defn funcc [funca funcb]
(-> funca
funcb))
但是当在 REPL 中运行其中任何一个并调用 funcc 时,我得到
传递到的参数数 (2( 错误:b/eval19367/fn
定义 funcc
的正确语法是什么,以便它可以获取传递给它的第一个参数的输出,将其用作传递的第二个参数的输入,然后返回结果?
这应该采用
(funca :add-z {:a 1 :b 2 :c 3})
的结果(这将是{:a 1 :b 2 :c 3 :z 26})
并将该结果用作(funcb :add-y-and-count-elements {:y 25})
的输入,然后返回结果{:a 1 :b 2 :c 3 :y 25 :z 26}
根据这个描述,你的funcc
实际上只接受一个参数(调用funca
的结果(,所以它应该这样定义:
(defn funcc [data]
(funcb :add-element data {:y 25}))
并称之为:
(funcc (funca :add-z {:a 1 :b 2 :c 3}))
如果您始终想使用funca
应用于add-z
某些数据的结果调用funcc
,则可以将其更改为:
(defn funcc [data]
(let [result-from-funca (funca :add-z data)]
(funcb :add-element result-from-funca {:y 25})))
并称之为:
(funcc {:a 1 :b 2 :c 3})
使用 as-> 宏
(as-> {:a 1 :b 2 :c 3} data
(funca :add-z data)
(funcb :add-element data {:y 25}))
如果在第一个参数位置funca
并funcb
接受的数据,则可以使用->
箭头。如果两个都接受的数据排在最后的位置,则可以使用->>
甚至comp
,例如
(def funcc (comp (partial funcb :add-element {:y 25})
(partial funca :add-z)))
根据哪种转换对您正在编写的函数最有用,围绕 Clojures 常见的合成工具(箭头和合成(设计它们的签名。