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