Re: Optional.orElseChain ?
Hi Remi, Chasing this up. I have not joined the dark-side just yet... but can you log an issue for this? Thanks, Paul. On Apr 20, 2015, at 4:27 PM, Remi Forax fo...@univ-mlv.fr wrote: On 04/20/2015 01:39 PM, Paul Sandoz wrote: Hi Remi, I was gonna propose the same trick you mentioned in your last email :-) yes, it's the same as optional.map(Stream::of).orElseGet(() - Stream.empty()) (I use orElseGet() because Stream.empty() is not a constant !). 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 fo...@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) :-) Yes, yet another one. Note that technically, the only thing you need is to be able to do pattern matching on the two states, so if you have a way to do a flatMap() for the case with a value and a flatMap() for the case with no value, you're done. Doing a flatMap for the case with no value is exactly what you have called 'or'. So it's yet another method to add but it's the last one :) 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 OptionalT or(SupplierOptionalT mapper) { Objects.requireNonNull(mapper); if (isPresent()) { return this; } else { return Objects.requireNonNull(mapper.get()); } } yes, 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 OptionalT or(OptionalT a, Supplier? extends OptionalT b) { Objects.requireNonNull(a); Objects.requireNonNull(b); return a.isPresent() ? a : Objects.requireNonNull(b.get()); } static T OptionalT or(OptionalT a, OptionalT 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. But mixing static methods and instance methods is not readable too, instance methods goes left to right and static methods goes right to left. I am somewhat on the fence here... If you only knew the power of the Dark Side :) Paul. Rémi
Re: Optional.orElseChain ?
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 fo...@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 OptionalT or(SupplierOptionalT 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 OptionalT or(OptionalT a, Supplier? extends OptionalT b) { Objects.requireNonNull(a); Objects.requireNonNull(b); return a.isPresent() ? a : Objects.requireNonNull(b.get()); } static T OptionalT or(OptionalT a, OptionalT 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 OptionalType loadType(String name); public default TypeProvider chain(TypeProvider provider) { return name - { OptionalType 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 OptionalT 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
Re: Optional.orElseChain ?
On 04/20/2015 01:39 PM, Paul Sandoz wrote: Hi Remi, I was gonna propose the same trick you mentioned in your last email :-) yes, it's the same as optional.map(Stream::of).orElseGet(() - Stream.empty()) (I use orElseGet() because Stream.empty() is not a constant !). 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 fo...@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) :-) Yes, yet another one. Note that technically, the only thing you need is to be able to do pattern matching on the two states, so if you have a way to do a flatMap() for the case with a value and a flatMap() for the case with no value, you're done. Doing a flatMap for the case with no value is exactly what you have called 'or'. So it's yet another method to add but it's the last one :) 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 OptionalT or(SupplierOptionalT mapper) { Objects.requireNonNull(mapper); if (isPresent()) { return this; } else { return Objects.requireNonNull(mapper.get()); } } yes, 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 OptionalT or(OptionalT a, Supplier? extends OptionalT b) { Objects.requireNonNull(a); Objects.requireNonNull(b); return a.isPresent() ? a : Objects.requireNonNull(b.get()); } static T OptionalT or(OptionalT a, OptionalT 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. But mixing static methods and instance methods is not readable too, instance methods goes left to right and static methods goes right to left. I am somewhat on the fence here... If you only knew the power of the Dark Side :) Paul. Rémi 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 OptionalType loadType(String name); public default TypeProvider chain(TypeProvider provider) { return name - { OptionalType 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 OptionalT 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
Re: Optional.orElseChain ?
On 04/18/2015 01:58 AM, Andreas Lundblad wrote: On Fri, Apr 17, 2015 at 03:01:29PM -0700, Steven Schlansker wrote: On Apr 17, 2015, at 2:37 PM, Remi Forax fo...@univ-mlv.fr wrote: 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 OptionalT 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 ? We actually ran into the exact same problem, and wrote the following helper method: public static X OptionalX unlessOpt(@Nonnull OptionalX first, SupplierOptionalX second) { return first.isPresent() ? first : second.get(); } I don't think it's precisely the same as your solution, but it definitely indicates a missing method. There are similar discussion here: http://stackoverflow.com/questions/2456/get-value-from-one-optional-or-another and here: http://stackoverflow.com/questions/28818506/java-8-optional-orelse-optional Thanks Andreas, the second link provides a clever answer (which as usually with StackOverflow is not the most voted answer :( ), return name - loadType(name).map(Optional::of).orElseGet(() - provider.loadType(name)); by mapping using Optional::of, it creates an Optional of Optional then orElseGet can be used to unwrap it to either an Optional or if the Optional inside the Optional is empty by calling the supplier. while this solution works, it creates an Optional of Optional just to workaround the fact that there is no method orElseChain/orElseOptional. -- Andreas cheers, Rémi
Optional.orElseChain ?
Hi guys, I was trying to write a code that uses Optional and I think one method is missing. 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 OptionalType loadType(String name); public default TypeProvider chain(TypeProvider provider) { return name - { OptionalType 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 OptionalT 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
Re: Optional.orElseChain ?
On Apr 17, 2015, at 2:37 PM, Remi Forax fo...@univ-mlv.fr wrote: 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 OptionalT 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 ? We actually ran into the exact same problem, and wrote the following helper method: public static X OptionalX unlessOpt(@Nonnull OptionalX first, SupplierOptionalX second) { return first.isPresent() ? first : second.get(); } I don't think it's precisely the same as your solution, but it definitely indicates a missing method.
Re: Optional.orElseChain ?
On Fri, Apr 17, 2015 at 03:01:29PM -0700, Steven Schlansker wrote: On Apr 17, 2015, at 2:37 PM, Remi Forax fo...@univ-mlv.fr wrote: 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 OptionalT 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 ? We actually ran into the exact same problem, and wrote the following helper method: public static X OptionalX unlessOpt(@Nonnull OptionalX first, SupplierOptionalX second) { return first.isPresent() ? first : second.get(); } I don't think it's precisely the same as your solution, but it definitely indicates a missing method. There are similar discussion here: http://stackoverflow.com/questions/2456/get-value-from-one-optional-or-another and here: http://stackoverflow.com/questions/28818506/java-8-optional-orelse-optional -- Andreas