- An `public Optional<T> or(Optional<T> other)` so if optA is empty, then `optA.or(optB)` would return `optB`
- A `toStream` method on `Optional` (I believe this is coming in Java 9) or have a `Stream.flatMap` signature that flattens `Optional`s without needing to call `Optional.toStream` (Scala does this, arguable if this is an acceptable munge of Monadic types, but it's really convenient)
Ceylon OTOH is at least good design, though I don't think that outweighs the library and tool ecosystem that Scala has.
The fact that there's so much discussion on the new SIP (Scala improvement process) and SLIP (Scala library improvement process) issues is a testament that Scala is alive and well. This is what happens in a mature language: many people put stakes in the ground.
Also, Scala most certainly has a bright future to go with its vibrant present. EPFL is hard at work with dotty, which will be a simplification and improvement of Scala.
String foo;
if (parameter != null) {
foo = ... ;
}
else {
foo = defaultValue;
}
or even this, if you express all your transformations as a single expression: String foo = parameter != null
? ...
: defaultValue
I don't get it. Your way of doing seem awfully more verbose. Please note that
I'm not against Optional in general (although they are overplayed in my
opinion).Second thing, I can't shake off the feeling of inefficiency: building these closures up, calling them. Lots of indirection for something that's probably very simple. I wouldn't want to call this code in a hot loop. But then maybe it's not in a hot loop. Before you bring that up, the sufficiently smart (JIT) compiler doesn't exist. "Sometimes suprisingly dumb" is a better qualifier for many compilers.
Note that I work with Java, and use the Java 8 features a lot. I just think this isn't a really good example.
If you actually take the time to translate OP's code with your own, you will soon find yourself indented six levels with "if (a != null) { ... if (b != null) { ... if (c != null) {...
You get the idea.
Monads (the type class that Optional belongs to) flatten all this boiler plate with a function called... flatMap! And you don't even need to know about it, all you need to do is chain the calls like OP did:
Optional.ofNullable(paramater)
.filter(...)
.map(a -> ...)
.map(b -> ...)
.orElseGet(() -> ...)
.orElse(defaultValue)
without having to check against null every step along the way.1 - http://mail.openjdk.java.net/pipermail/lambda-dev/2011-Septe...
Java probably followed Scala's notation, which is probably derived from mathematics where ↦ is an application (a function) and ⇒ is a simple logical implication.
Doesn't matter much in the long run, you'll get used to whichever your language favors after just a few days or writing code in it.
Do standard collections have groupBy? You can go a long way with groupBy and zipWith operations, which are a pair like map-reduce but for in-memory handling.
#1- If I'm dealing with some legacy code that I don't know well, and it's mapping from one object to a property of it that is another object... well, I'm not 100% certain it's not null.
.map(a -> a.getB())
.map(b -> b.getC())
if a.getB() is null, Optional eats it and I'm safe from NPE- I just an a non present Optional value. .map(a -> a.getB().getC())
If B is null, I'm going to NPE here (... right? I'm like 99% sure of that, but correct me please). And there are counter arguments like "never be null", etc, but I've got legacy code to cleanup, and no one taught the person who wrote it that particular lesson.#2- Ease of understanding. Little jumps rather than big ones. Makes the code easier to understand for the next guy who has to work on it. As much as I can, I try to write code that requires no commenting- because it's so clean it's not needed.
#3- The compiler will (or will eventually) optimize it into a single map anyways. Compilers are smart and keep getting smarter. So long as my big-O runtime is fine, I just focus on ease of understanding of my code.
I believe they are automatically combined before the results of the stream are forced.
String foo = defaultValue;
if (parameter != null && ...) {
foo = doAAndB(parameter);
}Comparing your code and mine, I ask you this: which one do you thing is more maintainable after 5 years of edits?
Each time a new developer needs to add a new case, a new rule, a new whatever, on my Optional (ab)usage, they just add a new line in the appropriate spot, a .filter or a .map or whatever. In yours it's far less clear.
Optional, for me, is wonderful because it lets me have a single return statement. A lot of the code in Java I'm replacing with this pattern is the stuff that has 5 different returns after checks. Crusty old stuff, but the business logic it's running has grown the way it has for good reasons.
The biggest worry I have right now is the story on debugging code with Optional bastardized FP. I know I'm going to learn some lessons soon enough, lol.