2

I'm working to replace the unapply method on a case class's companion object with my own implementation. And after investigating lots of different tangents related to implementing unapply, it appears there is a null guard in most of them, both in the compiler generated code and in the implementations where it is explicitly being redefined. The code from the compiler generated code for unapply looks similar to this (some of them use eq instead of ne):

def unapply(location: Location): Option[(Double, Double)] =
  if (location ne null)
    Some((location.longitude, location.latitude))
  else
    None

Given there should be absolutely no use of null in pure (i.e. idiomatic) Scala code, why is this null check being performed? Does it have something to do with Java interop (because Java is still addicted to exploiting null) leaking into the unapply method? What, if any, undesirable consequences will I suffer if I remove the check because I have eliminated the possibility of the case class instance to which the unapply method is being passed can be null nor invalid? IOW, what's the harm of replacing the above implementation with this one?

def unapply(location: Location): Option[(Double, Double)] =
  Some((location.longitude, location.latitude))
chaotic3quilibrium
  • 5,661
  • 8
  • 53
  • 86
  • [this](https://stackoverflow.com/questions/7885151/overloading-unapply-method-in-case-classes-scala) may partially answer your question – Bogdan Vakulenko May 27 '19 at 19:58
  • I read through that answer and couldn't find anything addressing the null check, other than his answer ALSO included the null check. The original question posted was too far off of my specific question for me to find it useful in definitively answering my question above. – chaotic3quilibrium May 27 '19 at 20:42
  • 2
    If you can guarantee that `Location` will never be `null`, then no harm. Emphasis on "if". – Lasf May 27 '19 at 21:47
  • 1
    @Lasf Got it. Given that is the assumption I make throughout ALL of the Scala code I have ended up using and writing for the last +8 years (and it is clearly the default assumption of the greater Scala community), it seems like a trivial guarantee. The onus is on whomever is doing Java interop to contain and constrain any sort of null "leak" that could infect Scala code, including getting to my Scala code, and especially including hitting my `unapply` method. – chaotic3quilibrium May 27 '19 at 21:58

1 Answers1

1

Otherwise, this would give very surprising behavior:

nullableJavaMethod() match {
  case Location(lat, long) => "Handle location here!"
  case null => "Handle null here!"
}

You might prefer another approach to handling null, but that doesn't mean you should make cases like the above crash with NPE if someone prefers that approach. Note that this is specific to unapply, as other methods will not suffer from the problem above.

Brian McCutchon
  • 8,354
  • 3
  • 33
  • 45
  • This answer doesn't work as it isn't my preference about which my question asks. I am asking why a null guard is present in Scala only code where it is idiomatic to eradicate all references to null, including and ESPECIALLY null guards. Your code above is trivially altered to be idiomatic Scala code by changing it to `Option(nullableJavaMethod()) match { case Some(Location(lat, long)) => "Handle location here!"; case None => "Handle null here!"}` – chaotic3quilibrium May 29 '19 at 13:00
  • @chaotic3quilibrium Still, most people -- especially beginners -- will expect the code I provided to work, and would be very surprised if it fails. We shouldn't set traps for beginners, especially runtime traps. Besides, I can think of a few reasons to use `null` in Scala (few and far between), such as [performance](https://github.com/scala/scala/blob/1486a671c11e5770144404e3df4ee1b31fab2066/src/library/scala/collection/mutable/RedBlackTree.scala#L31) and [optional implicits](http://missingfaktor.blogspot.com/2013/12/optional-implicit-trick-in-scala.html). – Brian McCutchon May 30 '19 at 00:13