Getting a nil where you are supposed to have an Optional.
In "pure" Scala (not in the FP sense, but just without mixing with Java) something like that is almost impossible.
For Scala 3 there are improvements. It's "null safe" as long as you opt-in (modulo Java libs, and of course doing stupid things like casting a null to some other type).
https://docs.scala-lang.org/scala3/reference/other-new-featu...
When you have people without clue on the team no language will safe you. You can also crash Haskell programs by throwing exceptions or just using List.head…
Is there really that much of a difference between those cases?
I agree though that in an interface, Optional conveys a more explicit meaning than something pointer-like, which is always a good thing.
Go programs crash at runtime. In general, program failures and bugs should surface as soon as possible. Ideally no later than compile time. Instead, Go makes you wait until the app is running.
For an app that has a lot of configuration options, for example, there can be a latent bug that crashes the binary for some options. And that bug may not be detected for months because nobody was using that combination of config options.
The only real defense of this is to pepper your code with a bunch of nil checks. But these nil checks are also hard to test, so Go devs just learn to ignore missing code coverage. In fact, your code coverage metrics look better if you don't check for nil.
I'm sure at some point Go or a library will offer a version of optional types that is well-adopted. But my point is that by the time Go was designed, null references were already widely considered a bad idea and the source of a huge class of computer bugs. Go still deliberately designed them into the type system.
Well, of course, if your end users, the business users, are okay if you present them an "optional result" which might or might not be a result, then Optionals/Either _are_ the cure. Unfortunately most end users are pissed if you tell them that you optionally shipped their purchase or that the refund will either be credited to their CC or not.
I agree that it's nice to be explicit about optional stuff, but overall it's not been a huge deal in the projects I've been involved with.
If you don't need to manipulate pointers then nil really just represents a degenerate or optional value. For optional values these can be encoded any number of ways depending on the type system. One common pattern is an optional type. Another is to annotate the type to indicate that it might be null.
The idea is that if a programmer doesn't check that an nullable or optional type is missing then the program should fail at compile time instead of crashing at runtime. Golang chose to crash programs at runtime.
So for whatever reason, Go has decided that null pointer dereferences are not a big deal. But God help you if you try to comment out a variable use without assigning it to "_". Then the program fails to compile.
I think that's a good explanation of why people are so frustrated with this. There are lots of features like go fmt, go vet, the compiler checking that you use all variables and all imports that can feel a bit restrictive. But for something like null pointers, there is nothing. It's incoherent.
* separate pointer types (e.g. C++ pointers v references)
* a built-in sigil / wrapper / suffix e.g. C#'s Nullable / `?` types
* a bog-standard userland sum type e.g. Maybe/Option/Optional
In modern more procedural languages the third option often will have language-level (non-userland) facilities tackled on for better usability but that's not a requirement.
For cases (2) and (3) it can (depending on language and implementation) also provides a mechanism for making other value types optional without necessarily having to heap-allocate them.