Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a simple way of defaulting out of bounds in nested Seqs in Scala?

Tags:

scala

I've got a Vector of Vectors that I'm accessing to apply a boolean function. i.e.

Vector[Vector[T]] where I'm going to execute something along the lines of f(myVector(i)(j)) where f is of type T => Boolean.

But this does not do bounds checking, and I can't get something really elegant.

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

where f(defaultT) would return false But I wish I could just set a default Value instead of a function.

I could use lift to give me an Option, but it doesn't compose well at the second level: myVector.lift(i) map (_.lift(j) map f getOrElse false) getOrElse false

Which does work, but is still really hard to read.

And then there's 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 seems like something that should be able to be decomposed easier than what I can achieve. And if I add a 3rd layer, it's gets even uglier.

Are there other options?

Disclaimer: this is adapted from coursera's progfun course

like image 547
Stephen Avatar asked Nov 04 '13 09:11

Stephen


1 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 key idea is to defer unwrapping (or mapping) the Option for as long as possible. This approach will generalize quite naturally to more than two dimensions.

This is pretty close to equivalent to the for-comprehension in your answer (assuming you meant to include lift in there), but once you have to wrap the comprehension in parentheses I personally tend to find the desugared version clearer.

like image 71
Travis Brown Avatar answered Sep 24 '22 01:09

Travis Brown