Optional.orElseChain ?
Paul Sandoz
paul.sandoz at oracle.com
Mon Apr 20 11:39:23 UTC 2015
Hi Remi,
I was gonna propose the same trick you mentioned in your last email :-)
Similar tricks are possible for other cases like an equivalent of the recently added ifPresentOrElse, but that was considered a little obtuse.
On Apr 17, 2015, at 11:37 PM, Remi Forax <forax at univ-mlv.fr> wrote:
> Hi guys,
> I was trying to write a code that uses Optional and I think one method is missing.
>
There is always one more (or four more including the primitive variants) :-)
We avoided supporting both the present and absent axes in the intermediate operations (e.g. additional methods with a supplier on absence).
This seems like a special intermediate operation, injecting an alternative optional on absence, rather than associated with the orElse terminal operations that return T:
public Optional<T> or(Supplier<Optional<T>> mapper) {
Objects.requireNonNull(mapper);
if (isPresent()) {
return this;
} else {
return Objects.requireNonNull(mapper.get());
}
}
But it has some terminal like qualities to it. It really only makes sense once, or once after each flatMap. I am concerned that a bunch of these sprinkled within a sequence of fluent calls might make it hard to reason about.
As such a static method might be more appropriate, but then it's easy for someone to add one in their own code:
static <T> Optional<T> or(Optional<T> a, Supplier<? extends Optional<T>> b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);
return a.isPresent() ? a : Objects.requireNonNull(b.get());
}
static <T> Optional<T> or(Optional<T> a, Optional<T> b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);
return a.isPresent() ? a : b;
}
Perhaps the non-obvious thing about these is a null return should not be allowed.
I am somewhat on the fence here...
Paul.
> Let suppose I want to load a type (like a class, an interface, etc) that can come
> either by reflection, or by using ASM.
> I will write an interface TypeProvider that is able to load a Type and
> i will chain the different type providers like this:
>
> TypeProvider asmTypeProvider = ...
> TypeProvider reflectionTypeProvider = ...
> TypeProvider provider =
> asmTypeProvider.chain(reflectionTypeProvider).orFail();
>
> so I've implemented TypeProvider like this:
>
> public interface TypeProvider {
> public Optional<Type> loadType(String name);
>
> public default TypeProvider chain(TypeProvider provider) {
> return name -> {
> Optional<Type> type = loadType(name);
> return type.isPresent()? type: provider.loadType(name);
> };
> }
>
> public default TypeProvider orFail() {
> return chain(fail());
> }
>
> public static TypeProvider fail() {
> return name -> Optional.empty();
> }
> }
>
> As you can see the code is not bad but the code of chain() could be simplified
> if there was a way on Optional to call a Supplier of Optional if an Optional is empty.
> Currently, orElse() takes a value, orElseGet takes a lambda that will return a value
> and there is no method that takes a lambda and return an Optional
> (like flatMap but but with a supplier that will be called if the Optional is empty).
>
> If we add the method orElseChain(Supplier<? extends Optional<T>> supplier)
> perhaps with a better name ?, then the code of chain is better:
>
> public default TypeProvider chain(TypeProvider provider) {
> return name -> loadType(name).orElseChain(() -> provider.loadType(name));
> }
>
> Am i the only one to think that this method is missing ?
>
> regards,
> Rémi
>
More information about the core-libs-dev
mailing list