5 ms·
The way Optional is/could at the time be implemented is far from performant, so they probably just didn’t want to overrely on such an abstraction. Even intellij
by kaba0 4y ago
The way Optional is/could at the time be implemented is far from performant, so they probably just didn’t want to overrely on such an abstraction. Even intellij’s default linter will call out on you if you use it as a class field for example.
While I do like more pure FP languages very much, I don’t think there is all that much value in everything being a value besides some mathematical elegance. Besides, a throwing exception can be turned into a value via a try-catch block, and can be just as easily tested as if it were a value, so where is the downside?
Exceptions are for exceptional situations, result types can still be used for very much expected ones. E.g. a primitive file read operation returning either a byte or EOF is great as a result type. Some specific IOException is better modeled as an exception which you might not be interested in handling at that level.
With all that said, I’m interested in the newer generation of languages with effect types that might bridge this gap.
- lmm 4y ago> While I do like more pure FP languages very much, I don’t think there is all that much value in everything being a value besides some mathematical elegance. Besides, a throwing exception can be turned into a value via a try-catch block, and can be just as easily tested as if it were a value, so where is the downside? It's really cumbersome in practice. E.g. when processing results from a database query (say), you probably want to call some callback for every row and then close the transaction and return the result of that callback. But handling exceptions around that becomes a significant pain. Once you've used a language with proper result types you don't want to go back, IME.
- kaba0 4y agoIf the exception is something you can handle at that function’s scope, just put it inside a try-catch. Otherwise, let it bubble up and let it close the transaction (or however you want to handle that). If anything, I feel it is easier to do with Java than in, say, Haskell though I will add that my experience with Haskell doing db queries is limited.
- lmm 4y agoUsually what you want is to go through the rest of the rows, finish the batch and close the transaction, and then handle all the errored rows at a higher level. "Bubble up by default" works in simple cases but falls apart as soon as you're doing any remotely high-throughput work (which has to mean chunk-at-a-time processing decoupled from the orchestration), and ends up doing more harm than good, IME. And note that in Java it's outright impossible to catch exceptions from a generic expression while preserving their type - you have to copy/paste your functions for each number of possible exception types you want to be able to handle.
- kaba0 4y agoI don’t see why this wouldn’t be performant: void transactionBoundary() { var list = someLongListOfElems; var resultList = List.of(); // a sum type for success and error conditions for (var l : list) { try { resultList.add(process(l)); } catch (SpecificException e) { // add to resulList or errorList or whatever to further process those instances. // You can just use SpecificException’s fields … } } }