在Clojure中处理Java Optional < T >

Dealing with Java Optional in clojure

我正在编写与外部Java库交互的Clojure代码。 方法之一返回Java Optional对象。 假设它返回Optional,并且我需要将Optional对象中的字符串值更改为小写。 如果我用Java编写代码,我会使用map方法:

1
2
3
4
Optional<String> ret = someObj.someMethod();
ret.map(String::toLowerCase)
   .map(...)
   .orElse("x");

因此,我需要在Clojure中调用someObj.someMethod(),并且必须执行类似的工作。 我发现的是:将Clojure函数作为java.util.Function传递

所以我写了这样的代码:

1
2
3
4
5
6
7
8
9
(defn ^java.util.function.Function jfn [f]
  (reify java.util.function.Function
    (apply [this arg] (f arg))))

(let [ret (.someMethod someObj)]
  (.. ret
      (map (jfn (fn [x] (s/lower-case x))))
      (map (jfn (...)))
      (orElse"x")))

为了将clojure函数传递到期望Java lambda的地方,我使用了如上定义的jfn。 实际上,它工作正常。

但是我不确定这是最好的方法,因为我必须在Java的Function中包装调用Java方法的clojure函数。

有没有更好/更简单的方法可以做到这一点? 如果我们可以直接调用Java StringtoLowerCase方法会更好。


我不确定它是否适合您的用例,但是您可以在早期将" Optional"拆箱,并使用some->宏进行类似的空短路功能组合。

即使您需要一个Optional及其后的值,也可能更容易提早取消装箱该值并稍后重新装箱该值,而不是互操作Function

1
2
3
4
5
6
7
8
9
10
11
(defn optional->nilable [this]
  (when (.isPresent this)
    (.get this)))

(def maybe (Optional/of" something"))

(some-> (optional->nilable maybe)
        (clojure.string/trim)
        (not-empty)
        (clojure.string/upper-case))
; =>"SOMETHING"

然后,如果您需要转换回Optional

1
(Optional/ofNullable *1)