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 对java对象使用类似于解构的语法_Clojure - Fatal编程技术网

Clojure 对java对象使用类似于解构的语法

Clojure 对java对象使用类似于解构的语法,clojure,Clojure,我正在编写代码,因此我必须遍历作为Java类实现的相当复杂的nexted数据结构,主要是POJO。我喜欢在使用clojure映射或记录时如何使用多级解构语法——我认为这比使用。或->操作 例如,我希望能够编写以下代码(由以下代码组成): 我现在的做法是,我有一组“桥接”函数,可以将给定类型的Java对象转换为映射。例如,它可能如下所示: (defn map-account [account] {:registration-date (.getRegistrationDate account)

我正在编写代码,因此我必须遍历作为Java类实现的相当复杂的nexted数据结构,主要是POJO。我喜欢在使用clojure映射或记录时如何使用多级解构语法——我认为这比使用。或->操作

例如,我希望能够编写以下代码(由以下代码组成):

我现在的做法是,我有一组“桥接”函数,可以将给定类型的Java对象转换为映射。例如,它可能如下所示:

(defn map-account [account]
  {:registration-date (.getRegistrationDate account)
   :order-history (map bean (.getOrderHistory account))
   :personal-data (bean (.getPersonalData account)})
这是可行的,但是有很多容易出错的样板文件(例如,假设account.getPersonalData()返回null),我想知道是否有一种方法可以使用类似映射分解的语法来处理Java对象,这种语法或多或少是“开箱即用”的

经过思考,如果它是实际的解构或类似的东西(例如,一些古怪的宏),只要它能给我与前者相比的表现力,我就不珍贵了。如果可以用一种惰性的方式完成,例如,对象图的分支根本不会被遍历,除非它们被实际访问

编辑:使用
clojure.core.bean
clojure.java.data
可以实现类似的功能,后者是递归的,前者不是。我知道他们可能会扮演一个角色,事实上,我在上面的例子中使用bean

我使用这些方法的主要问题是它们缺乏灵活性,不允许对结果进行任何调整。举几个可能非常有用的例子:

  • 其中一个对象可能与JavaBeans约定部分不兼容
  • 可能需要扁平化层次结构的某些部分,尤其是在底层JavaAPI非常惯用的情况下。在某些API中,经常会为通常组合在一起的成对对象创建实用程序类,例如。在Clojure中,它只会使代码更加复杂
  • 对递归应该走多远的控制是有限的。对于重要的对象图,它可能非常昂贵

您看过
clojure.core/bean

(bean (java.util.Date.))
这将使用getter和setter将Java对象转换为Clojure映射:

{:day 3,
 :date 8,
 :time 1578498930902,
 :month 0,
 :seconds 30,
 :year 120,
 :class java.util.Date,
 :timezoneOffset 0,
 :hours 15,
 :minutes 55}

尽管它不会递归执行,但为此,您可以使用
clojure.java.data
。这是在这个问题中描述的:

我认为这个问题更多的是关于如何将对象转换为Clojure数据,而不是具体的关于解构,即如果您解决了转换问题,那么解构问题已经解决了

Clojure 1.10定义了和。您可以为您的类型扩展
Datafiable
协议,并完全控制它们如何表示为数据。下面是一个使用
java.net.URI
的简单示例:

(extend-protocol Datafiable
  java.net.URI
  (datafy [u]
    {:host (.getHost u)}))

(datafy (java.net.URI. "http://clojure.org"))
=> {:host "clojure.org"}
它还定义和
可导航
,可用于延迟导航,例如处理循环结构或实现成本高昂的数据


我认为
bean
类函数(涵盖一般情况)与
datafy
nav
的某种组合应该会给您提供所需的所有控制/灵活性。

您检查过吗?有用的库。但我认为java.data是另一种方式?例如,从clojure映射到对象?哦,等等,您也有,自述文件中没有提到它。正如我在下面回答的,我的bean和java.data的主要问题是无法自定义映射。有些对象可能不是完全一致的,而且根本无法解决itI问题。在我目前针对某些对象的方法中,我使用bean。我对bean和java.data的主要问题是不可能定制映射。有些对象可能不是完全一致的,根本没有地方可以解决它。另一个有点小的问题是,它不处理循环,尽管在我的案例中这不是一个问题,是的,我也偶然发现了这一点,并开始使用它。这并不理想,因为纯解构将允许延迟查找,而datafy必须预先构建图形。如果有一个称为Destructurable的协议,那就太好了,它将实现一个等价于使用密钥获取的协议。不过,这很好
(extend-protocol Datafiable
  java.net.URI
  (datafy [u]
    {:host (.getHost u)}))

(datafy (java.net.URI. "http://clojure.org"))
=> {:host "clojure.org"}