Вопрос

Скала предлагает иерархию занятий Option[T], Some[T] extends Option[T], а также None extends Option[Nothing] что я нашел полезным для обертывания вызовов метода Java, которые могут вернуть null, среди прочего:

val result = Option(someJavaMethodThatReturnsNull())

result действует как последовательность нуля или одного элемента, в зависимости от того, возвращал ли метод Java объект или null. Option есть методы, как map, filter, и т. д., что вы можете использовать так же, как и в последовательности, и либо вернуть новую последовательность (Some), если оригинал был Some[T], или же None Если оригинал был None.

Похоже, что функция Clojure seq ведет себя так же: (seq x) будет последовательность одного элемента, если x не нулевой или nil Если x null. Это значение может быть передано в (map ...), (filter ...), и т. д., как Scala Option методы

Я что-то упускаю? Имеет ли этот шаблон смысл? Это "Эврика!" Момент, который очевиден для опытных программистов Clojure?

Это было полезно?

Решение

Нет. seq вернет абстрактный, последовательный взгляд на коллекцию в случае, если коллекция не будет пустой. nil в противном случае. Так что это совершенно не связано с тем, что вы хотите. Однако вы можете использовать nil в IF -тестах. например.

(when-let [thing (.someMethodThatReturnsSomethingOrNil other-thing)]
  (run-only-when thing is-not-nil-or-false))

Это то, что вы намерены?

Редактировать: Остерегайтесь ложных.

Другие советы

Вы всегда могли бы использовать Может, Монада, который близок к опции Scala (и, может быть, Haskell), конечно, без статического типа безопасности.

Также есть Семья? Функции потока (.?.. Лучший выбор для Java Interop)

Вы, безусловно, можете использовать последовательность Clojure, чтобы представлять ноль, одно или несколько возвратных значений.

Это разумный подход и очень идиоматический, если ваша функция фактически будет возвращать коллекцию.

Однако я бы нет Рекомендую использовать последовательность для эмуляции типа опции. Это, вероятно, путает пользователей вашего API. В Clojure нормальный и идиоматический способ - просто вернуть нуль, если значение недоступно, и вернуть значение напрямую, если оно есть.

Сравнивать:

  (if-let [a (function-that-returns-nil-or-result)]
    (do-something-with a))

С тем, что вам понадобится, если бы вы использовали последовательность для эмуляции типа опции:

  (if-let [a (function-that-returns-a-possibly-empty-sequence)]
    (do-something-with (first a)))  

Я определенно предпочитаю первый вариант .... зачем нам нужен или хотим, чтобы пользователь API не распаковал результат с последовательности с first?

В целом, NIL работает довольно хорошо в Clojure (намного лучше, чем на других языках), потому что:

  • Все библиотечные функции интерпретируют NIL как пустую последовательность, поэтому вы с меньшей вероятностью столкнетесь с NullPointerExceptions.
  • NIL также считается «FALSEY», поэтому может быть удобно использоваться в логических операциях.

(seq x) вернется nil если x является nil или пустая коллекция. Однако, map, filter и т. д. примет nil Как их аргумент сбора (то есть они не сломаются) и возвращают пустую последовательность. Это может дать результат, который вы ожидаете от Scala Option утверждение.

Следующее будет возвращать пустую последовательность:

(map (fn [x] x) (seq nil))
(map (fn [x] x) (seq `()))
(filter even? (seq nil))
(filter even? (seq `()))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top