Hacker News new | ask | show | jobs
by mark242 3428 days ago
Your very first method has a return buried in the middle of your code. That is a gigantic red flag.

Look, what you're trying to do is simple.

  getNumbers.fold(println("Failed to load numbers"))(nums => nums.foreach(println))
That's the Scala version, but I'm sure there's a Java version of the same code. This code assumes that getNumbers returns Option[List[Int]], which your compiler can guarantee. If you want something that's a little bit more readable, try this:

  getNumbers match {
    case Some(nums) => nums.foreach(println)
    case None => println("Failed to load numbers")
  }
No null check, no loops, just very simple easy-to-read bulletproof code. This code cannot generate a NPE at all, ever.
1 comments

The first option ins completely unreadable to me. I cannot imagine that ever scaling well.

The second option, as I have stated many times in this thread, is far preferable to null. Java does not support it but when it does I will like it.

"* No null check, no loops, just very simple easy-to-read bulletproof code. This code cannot generate a NPE at all, ever.*"

The NPE isn't the illness, it's the symptom. It's the symptom of a far larger problem in your program: unhandled or otherwise unexpected state. That's why I like the match example. It forces you to expect all of the states of your program. The first example does neither. It hides flow and operation in a single (ever-expanding) line. Far from ideal in any case in my book.

As soon as Match is supported in Java I'll change my opinion. Until then I'm stuck. You get nothing better from the Java version in terms of readability.

Fold is incredibly important. You should learn it. https://en.wikipedia.org/wiki/Fold_(higher-order_function)

In Scala, the debate between using fold on an Option or using map and getOrElse is almost as old as the language. The method signature for this is:

  def fold[B](ifEmpty: => B)(f: (A) => B): B
That is to say, fold always returns type B, and takes two arguments. The first takes a function returning type B if the option is "empty" (None) and the second takes a function that is called with the contents of the Some. As you can see, it's syntactic sugar for map and getOrElse.

  def map[B](f: (A) => B): B

  def getOrElse[B](f: => B): B
If it's syntactic sugar for map and getOrElse what is really gained? If the definition of fold is mapAndGetOrElse why add an additional concept to burden programmers minds with? GetOrElse is independently useful and everyone needs to know map anyway. Using fold just seems like a lost opportunity to teach someone getOrElse with no real benefit.

You make the Understanding This Codebase 101 curriculum some percent longer without making your programmers any better.

If it's terseness, I don't really think one symbol is any verbosity benefit over two. Same order of magnitude, same cost. It's a rounding error in brevity. People way overvalue terseness.

And the cost of people missing chances to learn getOrElse has got to be massive.

I haven't used Scala for years, but fold[0] is one of the functional programming building blocks. It's applicable across languages and data types.

It looks like syntactic sugar here, but it's really not. It's just a function that is more commonly used on collections with more than one item.

[0] also reduce, inject, aggregate, and other synonyms, because naming is hard

map and getOrElse are syntactic sugar for fold, not the other way around.
>The first option ins completely unreadable to me. I cannot imagine that ever scaling well.

It's actually trivial, and has been used in all kinds of languages, and scaled just fine, since the 60s.