初始化 Java 对象的 Clojure 惯用方法

Posted

技术标签:

【中文标题】初始化 Java 对象的 Clojure 惯用方法【英文标题】:Clojure-idiomatic way to initialize a Java object 【发布时间】:2011-05-17 21:57:50 【问题描述】:

我正在尝试找到一种 Clojure 惯用的方法来初始化 Java 对象。我有以下代码:

(let [url-connection
      (let [url-conn (java.net.HttpURLConnection.)]
        (doto url-conn
          (.setDoInput true)
          ; more initialization on url-conn
          )
        url-conn)]
  ; use the url-connection
  )

但它似乎非常尴尬。

有什么更好的方法来创建HttpURLConnection 对象并在稍后在代码中使用它之前对其进行初始化?

更新:看来(doto ...) 在这里可能会派上用场:

(let [url-connection
        (doto (java.net.HttpURLConnection.)
          (.setDoInput true)
          ; more initialization
          ))]
  ; use the url-connection
  )

根据doto 文档,它返回它正在“执行”的值。

【问题讨论】:

【参考方案1】:

正如我的问题更新中所解释的,这是我想出的答案:

(let [url-connection
        (doto (java.net.HttpURLConnection.)
          (.setDoInput true)
          ; more initialization
          ))]
  ; use the url-connection
  )

也许有人能想出一个更好的。

【讨论】:

您还想要什么?代码尽可能少。 我没有读过 Barski 的书,但是 CL 确实有数组和哈希表。而且我认为,至少在这一点上,Clojure 可能很难与更快的 CL 实现的效率相匹配。 但我还要说,Clojure 的数据类型方法比 CL 更一致。恕我直言,Clojure 的部分设计比 CL 的相应位更好。 你是对的,对于很多事情来说,超高效并不是那么重要(尽管有时它很重要,我很高兴看到很多努力是进入使 Clojure 高效。)我之所以发表评论,主要是因为有可能从许多有关 CL 的书籍中得到对 CL 的错误印象。您可以在 CL 中以非常面向列表的方式进行编程(这对于某些事情来说效率很低),但这还不是全部。生产 CL 通常看起来很不一样。 我应该补充一点,我当然同意你的观点,比如字面语法,特别是 Clojure 中好的序列抽象确实可以让 Clojure 中的许多东西变得更好。我不认为任何经常使用 CL 的人会将它与“完美”这个词联系起来;)。 CL 有很多缺点,尽管一旦你熟悉了这门语言,它们中的许多缺点就会变得非常不重要,但有些缺点仍然很烦人——在某些情况下尤其如此。但话虽如此,至少对我来说,Clojure 和 CL 都没有严格地支配对方。 CL 有很多东西可以提供,尽管有缺点。【参考方案2】:

假设没有构造函数接受所有需要的初始化参数,那么我知道的只有你这样做的方式。

你可以做的一件事就是把它全部包装在一个这样的函数中:

(defn init-url-conn [doInput ...other params..] 
     (let [url-conn (java.net.HttpURLConnection.)]
        (doto url-conn
          (.setDoInput true)
          ; more initialization on url-conn
          )
        url-conn))

然后调用:

(let [url-connection
      (let [url-conn (init-url-con true ...other params..)]
  ; use the url-connection
  )

但是,这是针对每个对象的,只有在多次初始化该类的对象时才真正有用。

您也可以编写一个宏来接受所有方法名称和参数并执行此操作。但是,当被调用时,该调用不会比您的第一个示例短多少。

如果有人有更好的主意,我很想看看,因为前几天我也这样问自己..

【讨论】:

是的。 doto 的文档也有类似的例子:(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))

以上是关于初始化 Java 对象的 Clojure 惯用方法的主要内容,如果未能解决你的问题,请参考以下文章

什么是惯用的clojure:使用

Clojure 中的惯用错误处理

从clojure中的普通lisp替换(null x)函数的惯用方法

在 Clojure 的嵌套映射中关联多个键/值的惯用方法是啥?

惯用的 Clojure 函数别名

有没有一种惯用的方法来避免长的 Clojure 字符串文字?