Ternary and Null Coalescing

I apologize in advance is this is the wrong place, I’m brand new to this forum and on-and-off new to Scala as a whole.

My question is in regards to ternary operators in general and their related operator types, such as null coalescing.

Personally, I find them a joy to write and read when written appropriately (read: limited nesting). In the documentation on scala-lang.org, I found that the reason for Scala’s lack of these operators is cited as readability. While I most certainly understand this perspective I do have several questions regarding it/other perspectives I was considering. I was hoping that someone might be able to answer or rebut them?

  1. The first is more of an abstract question. It is impossible to force developers to write purely readable code. No matter what tools the language gives them to help enforce readability, engineers will find a way to make it over-complicated and unreadable. Are there any deeper reasons that I am missing?

  2. Let’s take a look at the following (admittedly dumb) example, assuming there is a function findPerson() that returns Option[Person] from a database somewhere.

    Scala Today:

    val person = findPerson().getOrElse(null)
    val name = if (person != null) person.name else "No person found"
    

    Scala with Ternary:

    val person = findPerson().getOrElse(null)
    val name = person != null ? person.name : "No person found"
    

    Scala with Null-Coalescing and Falsey-Null:

    val person = findPerson().getOrElse(null)
    val name = person.name ?? "No Person found"
    

    Are any of these anti-Scala? If so, why?

To clarify, I’m honestly asking this question to learn how to better write “Scala-like Scala”. One of the most fun parts of learning a language to me is learning the “-isms” of the language.

I love the language and this community, so thank you to everyone who has worked so hard to make this language what it is today!

Edit: I am aware of things like this, just sort of wondering why it is not in the language itself.

1 Like

These examples would probably elicit a comment if they came up during a code review, mostly because of the null. While this isn’t really the main point, I thought I might provide a quick couple of alternatives that are a bit more idomatic:

findPerson().fold("No person found")(_.name)
findPerson().map(_.name).getOrElse("No person found")

No real point in messing with null if you’ve already got an Option ¯\_(ツ)_/¯

4 Likes

None of those look like idiomatic scala today. Instead, we’d favour:

val name =
  findPerson()
    .map(_.name)
    .getOrElse("No person found")

More generally though, you’ll rarely see null, and never, ever see getOrElse(null). In the rare circumstances where it’s needed - almost always for java interop - you’d write findPerson().orNull

5 Likes

That’s much better. I knew there was a Scala way to go about this problem. Thank you for the reply!

Yet another great solution! Thank you, this makes much more sense.

Here’s another one then:

val name = findPerson() match {
  case Some(person) => person.name
  case None => "No person found"
}
2 Likes

There is one for the most problems on hand. And usually, I don’t get it right, either :slight_smile: Welcome to the board and Scala, shall it not be on-off anymore :slight_smile:

2 Likes

The options already given are probably unbeatable, but if you are transitioning from other languages, I find this pretty reasonable too (but less idiomatic):

val person = findPerson()
val name = if (person.nonEmpty) person.get.name else "No person found"

It does not change your code at all ands show you how to easily avoid the null. As to your ternary-operator part of the question, Scala 3 IIRC will allow you to omit parentheses and make this much more legible (especially on an IDE with colors):

val person = findPerson()
val name = if person.nonEmpty then person.name else "No person found"