Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Clojure中使用函数列表构建映射_Clojure - Fatal编程技术网

在Clojure中使用函数列表构建映射

在Clojure中使用函数列表构建映射,clojure,Clojure,我对Clojure还比较陌生,所以我在思考如何做以下工作时遇到了困难 从一个Java方法(来自reflect包)开始,我想提取各种属性,最后得到一个如下所示的映射: { :name "test-method :return-type "String" :public true } 由于构建键的逻辑可能相当复杂,我想链接一系列函数,这些函数接受当前映射和方法对象,并修改映射或按原样返回。比如: (defn build-public [acc method] (if (is-publi

我对Clojure还比较陌生,所以我在思考如何做以下工作时遇到了困难

从一个Java方法(来自reflect包)开始,我想提取各种属性,最后得到一个如下所示的映射:

{ :name "test-method
  :return-type "String"
  :public true
}
由于构建键的逻辑可能相当复杂,我想链接一系列函数,这些函数接受当前映射和方法对象,并修改映射或按原样返回。比如:

(defn build-public 
[acc method] 
(if (is-public? method) (assoc acc :public true) acc))
这可以称为:

(make-method-map method [build-public build-return-type build-name])

我尝试过几种不同的方法,但似乎无法奏效,任何建议都将不胜感激。

一种方法是使用
cond->
,它结合了
cond
->
的概念

(cond-> {:my-map 1}
  (= 2 2) (assoc :two-equals-two true)
  (= true false) (assoc :not-possible "hey"))
=> {:my-map 1, :two-equals-two true}

左侧的子句决定是否对右侧的表单求值,初始值在第一个位置穿行。

简单的方法是使用reduce:

user> (defn make-method-map [method fns]
        (reduce (fn [acc f] (f acc method))
                {} fns))
#'user/make-method-map-2

user> (defn make-name [acc method]
        (assoc acc :name 123))
#'user/make-name

user> (defn make-other [acc method]
        (assoc acc :something "ok"))
#'user/make-other

user> (make-method-map {:a 1 :b 2} [make-name make-other])
;;=> {:name 123, :something "ok"}

我会这样写
makemethodmap

(defn method-map [method]
  (-> {}
      (assoc :return-type (get-return-type method))
      (assoc :name (get-name method))
      (cond-> (public? method) (assoc :public? true))))
(defn method-map [method]
  (-> {}
      (assoc :return-type (get-return-type method))
      (assoc :name (get-name method))
      (assoc :public? (public? method))))
请注意如何将
cond->
(或
as->
->
)嵌套在
->
中。但是,将它们中的任何一个放在
->
或类似文件中可能并不像您预期的那样有效

这是为什么留给读者作为练习

实际上我会这样写:

(defn method-map [method]
  (-> {}
      (assoc :return-type (get-return-type method))
      (assoc :name (get-name method))
      (cond-> (public? method) (assoc :public? true))))
(defn method-map [method]
  (-> {}
      (assoc :return-type (get-return-type method))
      (assoc :name (get-name method))
      (assoc :public? (public? method))))
或者,如果我能侥幸逃脱的话,可以使用文字映射(一步不取决于下一步,等等)

但这并没有显示嵌套
cond->
的技巧

(cond-> {:my-map 1}
  (= 2 2) (assoc :two-equals-two true)
  (= true false) (assoc :not-possible "hey"))
=> {:my-map 1, :two-equals-two true}
如果你发现自己有一个函数向量,那么leetwinski的答案是好的。就像编程中的每一件事一样,这要视情况而定

编辑:
对于正在使用的函数向量的真实示例,请查看或中的拦截器概念。

我喜欢
reduce fns
选项,但这里有一个具有稍微不同的函数签名的替代方案:

(defn make-name  [method] {:name   (str (:a method) "-" (:b method))})
(defn make-other [method] {:a-is-3 (= (:a method) 3)})

(defn make-method-map [method fns]
  (into {} ((apply juxt fns) method)))

(defn make-method-map [method fns]
  (reduce merge ((apply juxt fns) method)))

(defn make-method-map [method fns]
  (apply merge ((apply juxt fns) method)))


(make-method-map {:a 1 :b 2} [make-name make-other])
; {:name "1-2", :a-is-3 false}

返回函数返回值的向量,此处不将
acc
作为输入参数,而是将
转换为
reduce
用于将这些哈希映射“合并”到最终结果中。最初我想使用
comp
,但是这些函数的样式没有那么“可组合”。

嵌套线程宏的事情解释得很好。这真的很棒。我一直在挖掘康德更多,真的很棒的工具!我最终实现了这个解决方案。它一直工作得很好。谢谢