Работа с Java опционально <T>в ближайшем будущем - PullRequest
1 голос
/ 02 апреля 2020

Я пишу код Clojure, взаимодействующий с внешней библиотекой Java. Один из методов возвращает Java Optional объект. Давайте предположим, что он возвращает Optional<String>, и мне нужно изменить строковое значение в объекте Optional, например, в нижний регистр. Я бы использовал метод map, если бы я написал код в Java:

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

Итак, мне нужно вызвать someObj.someMethod() в Clojure и выполнить аналогичную работу. Я нашел следующее: Передача функции Clojure как java .util.Function

Итак, я написал такой код:

(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 лямбда, я использовал jfn, определенный как выше. И на самом деле все работает отлично.

Но я не уверен, что это лучший способ сделать это, поскольку мне нужно обернуть функцию clojure, которая вызывает метод Java, внутри Java * Function.

Есть ли лучший / более простой способ сделать это? Будет лучше, если мы сможем напрямую вызывать метод Java String toLowerCase.

1 Ответ

3 голосов
/ 02 апреля 2020

Я не уверен, подходит ли он для вашего случая использования, но вы могли бы "распаковать" Optional на ранних этапах и использовать макрос some-> для создания аналогичной композиции функции замыкания на ноль.

Даже если вам нужно Optional со значением позже, может быть проще распаковать значение раньше и переназначить значение позже, чем Function interop.

(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)
...