Throwaway values - what is the best practice in Scala?

2.3k views Asked by At

WartRemover's NonUnitStatements requires that statements that aren't returning unit must have an assignment. OK, but sometimes we have to use annoying Java APIs that both mutate and return a value, and we don't actually hardly ever care about the returned value.

So I end up trying this:

val _ = mutateSomething(foo)

But if I have multiple of these, _ is actually a legit val that has been assigned to, so I cannot reassign. Wartremover also rightly will admonish for gratuitous var-usage, so I can't just do var _ =.

I can do the following (need the ; to avoid Scala thinking it is a continue definition unless I add a full newline everytime I do this).

;{val _ = mutateSomething(foo)}

Is there a better way?

2

There are 2 answers

3
bbarker On BEST ANSWER

I'm posting an answer, but the real credit goes to Shane Delmore for pointing this out:

def discard(evaluateForSideEffectOnly: Any): Unit = {
  val _: Any = evaluateForSideEffectOnly
  () //Return unit to prevent warning due to discarding value
}

Alternatively (or see @som-snytt's comments below):

@specialized def discard[A](evaluateForSideEffectOnly: A): Unit = {
  val _: A = evaluateForSideEffectOnly
  () //Return unit to prevent warning due to discarding value
}

Then use it like: discard{ badMutateFun(foo) }.

Unlike the ;{ val _ = ... } solution, it looks way better, and also works in the beginning of a block without needing to alter style (a ; can't come at the start of a block, it must come after a statement).

4
Joe K On

My general thoughts about linting tools is that you should not jump through hoops to satisfy them.

The point is to make your code better, both with fewer bugs and stylistically. But just assigning to var _ = does not achieve this. I would first be sure I really really don't care about the return value, not even asserting that it is what I expect it to be. If I don't, I would just add a @SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements")) and maybe a comment about why and be done with it.

Scala is somewhat unique in that it's a somewhat opinionated language that also tries to integrate with another not-so-opinionated language. This leads to pain points. There are different philosophies to dealing with this, but I tend to not sweat it, and just be aware of and try to isolate the boundaries.