Stream proposal and null results
Peter Levart
peter.levart at marand.si
Fri May 18 01:28:55 PDT 2012
On Thursday, May 17, 2012 07:09:32 PM Brian Goetz wrote:
>
> In the context of the discussion we're having, which is whether to use
> Optional<T> as the return type for Stream<T>.getFirst, this is not an
> issue, because the option-ness is likely to be hidden by the chaining:
>
> String s = people.filter(p -> p.age() > 18)
> .map(Person::getName)
> .getFirst()
> .getOrThrow(() -> new NoSuchPersonException());
Even if you don't commit to have Option<T> in the standard library, 3rd party libraries could interface with streams using .into(Fillable). For example:
public class Option<T> implements Fillable<T>
{
private boolean hasResult;
private T result;
@Override
public void addAll(Iterable<? extends T> source)
{
for (T t : source)
{
if (hasResult) throw new IllegalStateException("Not a single result");
result = t;
hasResult = true;
}
}
public T getOrElse(T defaultValue)
{
return hasResult ? result : defaultValue;
}
public T getOrElse(Factory<? extends T> defaultFactory)
{
return hasResult ? result : defaultFactory.make();
}
public <E extends Throwable> T getOrThrow(Factory<E> exceptionFactory) throws E
{
if (hasResult) return result;
throw exceptionFactory.make();
}
}
// so the chain above could be written as:
String s = people.filter(p -> p.age() > 18)
.map(Person::getName)
.into(new Option<String>()) // hm, new Option<>() does not work here currently :-(
.getOrThrow(() -> new NoSuchPersonException());
Regards, Peter
>
> Here, the Option has relatively little use on its own; you're going to
> immediately call one of the various getOrElse methods, and the fact that
> it is an Option<String> does not appear in the source code.
>
> Similarly, if we added an Option-bearing get-like method to Map (not
> saying we're going to do this), the same would be true:
>
> String s = map.getAsOption(key)
> .getOrElse(DEFAULT_STR);
>
> Since we're not proposing anything that returns List<Optional<T>> or
> anything like that, I don't get how your argument applies here, and it
> almost sounds like you're making the argument of "don't add any new
> generic container-like types to the library, because you increase the
> chance that people will use unwieldy generic names", which I can't say
> makes very much sense to me. It might be poor taste to have a
> nineteen-deep nested list of lists, but does that mean we shouldn't give
> people a generic List class?
>
> > I have a guidance rule that 1 level of generics is OK, 2 is
> > manageable, but 3 means you're probably missing a real domain class.
> > Optional<T> just gets you to that 2nd/3rd layer of generics faster
> > than necessary. I'd also note that those nested generics tend to be
> > harder for developers to rationalise about.
>
> That's a fine rule for your code. I just don't see how adding
> Optional<T> and adding a few methods that return Optional<T> move people
> any closer to violating that rule?
More information about the lambda-dev
mailing list