在 clojure 中处理 Java 可选 <T>

Dealing with Java Optional<T> in clojure

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

中编写代码,我会使用 map 方法
Optional<String> ret = someObj.someMethod();
ret.map(String::toLowerCase)
   .map(...)
   .orElse("x");

因此,我需要在 Clojure 中调用 someObj.someMethod() 并且必须执行类似的工作。我发现的是:

所以我写了这样的代码:

(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 函数。

有什么better/simpler方法可以做到这一点吗?如果能直接调用JavaStringtoLowerCase方法就更好了。

我不确定它是否适合你的用例,但你可以在早期 "unbox" Optional,然后使用 some-> 宏进行类似的短路-空函数组合。

即使您以后需要 Optional 和值,提前拆箱并稍后重新装箱可能比 Function 互操作更容易。

(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:

(Optional/ofNullable *1)