0

Per the documentation, find function in scala's collection wraps the resulting elements in Option object. In the below, the size operation ends in error; where as the endsWith produces correct result.

The second element in the list being null, both should error out / produce correct result.

val a1:String = "ABCDEF"
val a2:String = null
val res12 = List(ABCDEF, null)

res12 filter { _.size > 10 }              //errors out
java.lang.NullPointerException
  at scala.collection.immutable.StringOps$.length$extension(StringOps.scala:51)
  at scala.collection.immutable.StringOps.length(StringOps.scala:51)
  at scala.collection.SeqLike.size(SeqLike.scala:108)
  at scala.collection.SeqLike.size$(SeqLike.scala:108)
  at scala.collection.immutable.StringOps.size(StringOps.scala:33)
  at .$anonfun$res19$1(<console>:13)
  at .$anonfun$res19$1$adapted(<console>:13)
  at scala.collection.TraversableLike.$anonfun$filterImpl$1(TraversableLike.scala:251)
  at scala.collection.immutable.List.foreach(List.scala:392)
  at scala.collection.TraversableLike.filterImpl(TraversableLike.scala:250)
  at scala.collection.TraversableLike.filterImpl$(TraversableLike.scala:248)
  at scala.collection.AbstractTraversable.filterImpl(Traversable.scala:108)
  at scala.collection.TraversableLike.filter(TraversableLike.scala:262)
  at scala.collection.TraversableLike.filter$(TraversableLike.scala:262)
  at scala.collection.AbstractTraversable.filter(Traversable.scala:108)
  ... 28 elided

res12 find { _.endsWith("EF") }       //produces correct result
res20: Option[String] = Some(ABCDEF)
bad_coder
  • 11,289
  • 20
  • 44
  • 72
user3103957
  • 636
  • 4
  • 16

2 Answers2

3

both should error out / produce correct result

No they shouldn't.

filter() has to touch every element to see if it's in or out. If there's a bomb in the collection then it will be detonated.

find() is lazy. Find the 1st element to pass the predicate test and we're outa here. One and done.

jwvh
  • 50,871
  • 7
  • 38
  • 64
  • Thanks jwvh, I just swapped the element order in the list and I am getting the exception now. On a different note, I am going through Option usage in Scala collection. When we have a collection made of only Option objects (Some and None) and if we apply any methods on the collection (e.g: map , filter, fold), the methods will not process None. Am I correct ? – user3103957 May 06 '20 at 05:35
  • 2
    @user3103957, no. Which elements the method will process (in this case apply the supplied function) depends on the method. As @jwvh pointed out `find()` is lazy and stops iterating after the first match. Methods like `filter`, `map` and `fold` apply the function to all elements in the collection – CervEd May 06 '20 at 06:07
  • 2
    @user3103957; `None` elements get processed just like any other: `listOfOptions.count(_.isEmpty)` – jwvh May 06 '20 at 06:58
  • Thanks @CervEd and jwvh., I got another example that flatten will not process None. val x = List(Some(1), Some(2), None, Some(3), None); x.flatten gives List(1, 2, 3). So None is safely skipped by flatten. Hence it is very obvious that processing of None, depends on the called collection's method. – user3103957 May 07 '20 at 02:57
  • 2
    @user3103957; When you `flatten` a collection of options, the `None` elements are not skipped, they are removed, and for that to happen they have to be interrogated (processed) to determine if they are worthy of removal. It's the same with `List(List(2,3),List(),List(9,1)).flatten`. The empty `List` is not "skipped," it is processed like the others. – jwvh May 07 '20 at 03:30
  • Thank you, I am understanding now. I come across another scenario. In this piece of code: val x= Option("ABC"); x map { e => Option("XYZ") } --> returns Some(Some(XYZ)) which is surprising. If it was other collections (like: List, Set), it should return Some("XYZ"). So I understand in Option monoid, the map method is written differently. – user3103957 May 07 '20 at 05:21
  • 2
    `List("ABC").map(e => List("XYZ"))` returns `List(List(XYZ))` Doesn't look very different to me. – jwvh May 07 '20 at 06:04
  • Thanks jwvh. That was a brain fade moment when I write my above comment.I realized it now. Thanks again – user3103957 May 09 '20 at 06:58
1

This produces an error because you are calling size on a null String which is in fact a NullPointerException

scala> val s: String = null
val s: String = null

scala> s.size
java.lang.NullPointerException
  at scala.collection.StringOps$.size$extension(StringOps.scala:165)
  ... 32 elided
Brian
  • 20,195
  • 6
  • 34
  • 55