Forall semantics

Hi,

This is something that has puzzled me for some time, but I never thought about asking to a broader audience.

The forall method returns true if the collection or Option is empty. How does it even make any sense?

For example, we take an empty Option, all predicates making assertions about its content should return false. The same is valid for Scala collections.

@ val optEmpty: Option[String] = None
optEmpty: Option[String] = None

@ optEmpty.forall(_.startsWith("a"))
res6: Boolean = true

@ optEmpty.forall(_.startsWith("b"))
res6: Boolean = true

IMO, if something is empty and I want to make an assertion about its content than the predicate must always return false.

There is an open PR for play-json (see comment) that introduces forall on JsResult and it’s following the same logic. Fair enough, it’s good to keep consistency in the ecosystem. However, I was just wondering what is the rationale behind this choice.

@aaabramov pointed me to
http://blog.originate.com/blog/2014/06/15/idiomatic-scala-your-options-do-not-match which contains a good explanation for it.

forall and exists are quantifiers in logic that are defined to behave a specific way. You can also convert statements using one to statements using another. This might help you understand why forall works the way it does:

None.forall(_.startsWith("a"))

is equivalent to

!None.exists(!_.startsWith("a"))

Because there is no element in None, exists fails, and so !exists succeeds.

1 Like