Clojure seq as a replacement for Scala Option [T]

Scala offers a class hierarchy of Option[T] , Some[T] extends Option[T] and None extends Option[Nothing] , which I found useful for wrapping calls to Java methods that can return null , among other things:

 val result = Option(someJavaMethodThatReturnsNull()) 

result acts as a sequence of zero or one element, depending on whether the Java object returned an object or null . Option has methods like map , filter , etc. that you can use as you would in a sequence and either return a new sequence ( Some ) if the original was Some[T] , or None if the original was None .

It seems that the Clojure seq function behaves similarly: (seq x) will be a sequence of one element if x is not null or nil if x is null. Then this value can be passed to (map ...) , (filter ...) , etc., as Scala Option methods.

Am I missing something? Does this template make sense? This is "Eureka!" obvious moment for experienced Clojure programmers?

+4
source share
4 answers

No. seq will either return an abstract, consistent look in the collection if the collection is not empty. nil otherwise. So this is completely unrelated to what you want. However, you can use nil in tests. eg.

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

Is that what you intend?

Edit: Beware of false.

+1
source

You can always use perhaps a monad that is close to scala Option (and haskell Maybe) without static type security, of course.

Also have a family? streaming functions (.?. is the best choice for java interaction)

+2
source

You can use the Clojure sequence to represent zero, one or more return values.

This is a smart approach and very idiomatic if your function is expected to return a collection.

However, I would not recommend using a sequence to emulate a parameter type. This is likely to confuse your API users. In Clojure, the normal and idiomatic way is to simply return nil if the value is not available, and return the value directly if there is one.

For comparison:

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

What you will need if you used a sequence to emulate an option type:

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

I definitely prefer the first option .... why do we need or need the API user to unpack the result from the sequence using first ?

As a rule, nil works fine in Clojure (much better than in other languages), because:

  • All library functions interpret nil as an empty sequence, so you are much less likely to work in NullPointerExceptions.
  • nil is also considered "false", so it can be conveniently used in boolean operations.
+2
source

(seq x) will return nil if x is nil or an empty collection. However map , filter , etc. They accept nil as their collection argument (i.e. will not interrupt) and return an empty sequence. This may lead to what you expect from the Scala Option statement.

Each of them returns an empty sequence:

 (map (fn [x] x) (seq nil)) (map (fn [x] x) (seq `())) (filter even? (seq nil)) (filter even? (seq `())) 
0
source

All Articles