Oh wow. Beautiful, at least it works ^^
Bit of a coincidence but http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Of course it’s a bit useless without mandatory non-nullness in the rest of the JDK but there we go.
Cas
Way to make every piece of code calling into a library supporting Optional look ugly and bloated :emo:
Current Java code:
String name = car.getEngine().getType().name().toLowerCase(); // potential NPEs everywhere!
C#'s syntax to solve this problem:
string name = Car?.GetEngine()?.GetType()?.Name().ToLowerCase();
Java 8’s fix: (rewrite your entire model, bloat your callsites)
Optional forces you to actively unwrap an Optional to deal with the absence of a value; as a result, you protect your code against unintended null pointer exceptions.
public class Car
{
- public Engine getEngine() { return engine; };
+ public Optional<Engine> getEngine() { return Optional.of(engine); };
}
public class Engine
{
- public Type getType() { return type; };
+ public Optional<Type> getType() { return Optional.of(type); };
}
public enum Type
{
STEAM, GASOLINE, MUSCLE
}
- String name = car == null ? null :
- car.getEngine() == null ? null :
- car.getEngine().getType() == null ? null :
- car.getEngine().getType().name().toLowerCase();
+ String name = car == null ? null :
+ !car.getEngine().ifPresent() ? null :
+ !car.getEngine().unwrap().getType().ifPresent() ? null :
+ !car.getEngine().unwrap().getType().unwrap().name().toLowerCase();
It got worse, much worse… and not even close to C#'s approach… somebody point out my obvious mistake please. :persecutioncomplex:
[quote=“Riven,post:43,topic:49169”]
It is indeed pointless, unless you use the functional APIs:
String type =
Optional.of(new Car(new Engine(Type.GASOLINE))) // Optional<Car>
.flatMap(Car::getEngine) // Optional<Engine>
.flatMap(Engine::getType) // Optional<Type>
.map(Type::name) // Optional<String>
.map(String::toLowerCase) // Optional<String>
.orElse("<unknown type>"); // String
It becomes more interesting when the source is a stream, instead of a single value.
…somebody point out my obvious mistake please
The fact that the code looks like that ignoring the possibility of a NPE?
[quote=“Spasi,post:44,topic:49169”]
It is indeed pointless, unless you use the functional APIs:
I’d prefer adding support to the functional libraries instead… (and not go much further)
String type =
@@ optional(car)
@@ .optionalFlatMap(Car::getEngine)
@@ .optionalFlatMap(Engine::getType)
.map(Type::name)
.map(String::toLowerCase)
.orElse("<unknown type>");
It becomes more interesting when the source is a stream, instead of a single value.
Yeah, that was clear to me, I however think that the biggest problem with current code is method chaining, not with functional-style APIs.
I’d hate all business classes / libraries getting sprinkled with Optional. :emo:
Hmm… doesn’t Java 8 have the ?. and ?: operators though?
Cas
Hmm… doesn’t Java 8 have the ?. and ?: operators though?
Cas
[…snipped paragraph about Groovy, C# with ?: ?. syntax…]
OK, we diverged a bit and all this sounds fairly abstract. You might now wonder, “so, what about Java SE 8?”
Optional in a Nutshell
Java SE 8 introduces a new class called java.util.Optional
I took that as implying Java 8 takes another route. We’ll see.
yea Java 8 has possibilties for monads now, although its syntax might not be the most fluent. the future monad usually takes an async stream of data and does whatever computations on it, then you can fmap/bind a closure on it after its done.
but netflix has spit out a reactive way of handling streams https://github.com/Netflix/RxJava
I’ll have to check with JDK8 tomorrow about ?. and ?: … I don’t have high hopes though.
Cas
I love the princec idea but applied to constructors to have a destructor
public foo() {
...
} finally {
yourDisposableObject.dispose();
}
It will be nice to have a short object construction syntax when left & right is the same. Instead of
YourClassObject<Class1,Class2> var= new YourClassObject<Class1,Class2>(params);
have this
YourClassObject<Class1,Class2> var= new(params);
And to have by reference parameters instead of only by value
void swap(int a, int b){
int c=a; a=b; b=c;
}
swap(&a,&b);
int x, y;
if (x && y < 10) {
}
^ Not exactly like that, but at least a way to short comparisons like this