Is there an easy way to default out of bounds in nested Seqs in Scala?

I have a vector of vectors that I refer to in order to apply a boolean function. i.e.

Vector[Vector[T]] , where I am going to do something according to f(myVector(i)(j)) where f is of type T => Boolean .

But this does not check the boundaries, and I cannot get something really elegant.

I can use applyOrElse : myVector.applyOrElse(i, (_:Int) => Vector.empty).applyOrElse (j, (_:Int) => defaultT)

where f(defaultT) will return false But I would just like to set the default value instead of a function.

I could use the elevator to give me Option , but it doesn’t work well for the second level: myVector.lift(i) map (_.lift(j) map f getOrElse false) getOrElse false

Which works, but still hard to read.

And then there are the standard if / else blocks:

 if (myVector.size <= i) false else { val myVector2 = levelVector(i) if (myVector2.size <= j) false else f(myVector2(j)) } 

It just looks like it should be easier to decompose than what I can achieve. And if I add a third layer, it will become even more ugly.

Are there any other options?

Disclaimer: this is adapted from coursera progfun course

+7
scala
source share
2 answers

Take the following code from the question:

 myVector.lift(i) map (_.lift(j) map f getOrElse false) getOrElse false 

This can be rewritten as follows:

 myVector.lift(i).flatMap(_.lift(j)).fold(false)(f) 

Or, before fold was introduced in Scala 2.10:

 myVector.lift(i).flatMap(_.lift(j)).map(f).getOrElse(false) 

The basic idea is to postpone the expansion (or display) of the Option as long as possible. This approach will naturally generalize to more than two dimensions.

This is pretty close to the equivalent of for -consciousness in your answer (assuming you wanted to include lift there), but as soon as you need to wrap the understanding in parentheses, I personally tend to find the delayed version clearer.

+2
source share

I realized something that seems elegant, even if it went a little too far:

 (for { myVector2 <- myVector(i) t <- myVector2(j) } yield t) map f getOrElse false 

It is reasonable? It is certainly readable. Is it slow?

0
source share

All Articles