2016-02-15 7:48 GMT+01:00 Peter Levart <peter.lev...@gmail.com>: > > > What about even more permissive: > > static <T, S extends T> Stream<T> iterate3(S seed, Predicate<? super S> > predicate, Function<? super S, ? extends S> f) >
Hi Peter, yes, Function<? super S, ? extends S> instead of UnaryOperator<S> is indeed tempting. On the other hand, for my taste, I find the wildcard-ridden signature of iterate3 oversteps a certain complexity budget a little (that's just my personal opinion, of course). But you may be right - we already have such complex signatures in a couple of other places. The question is, whether it would be really useful. Regards, Stefan > > public class SignatureTest { > > static <T> Stream<T> iterate1(T seed, Predicate<T> predicate, > UnaryOperator<T> f) { > ... > } > > static <T, S extends T> Stream<T> iterate2(S seed, Predicate<S> > predicate, UnaryOperator<S> f) { > ... > } > > static <T, S extends T> Stream<T> iterate3(S seed, Predicate<? super S> > predicate, Function<? super S, ? extends S> f) { > ... > } > > > public static void main(String[] args) { > > Stream<Integer> si1 = iterate1(0, i -> i < 10, i -> i + 1); // OK > Stream<Integer> si2 = iterate2(0, i -> i < 10, i -> i + 1); // OK > Stream<Integer> si3 = iterate3(0, i -> i < 10, i -> i + 1); // OK > > Stream<Number> sn1 = iterate1(0, i -> i < 10, i -> i + 1); > > //SignatureTest.java:32: error: bad operand types for binary > operator '<' > // Stream<Number> sn1 = iterate1(0, i -> i < 10, i -> i + 1); > // ^ > //SignatureTest.java:32: error: bad operand types for binary > operator '+' > // Stream<Number> sn1 = iterate1(0, i -> i < 10, i -> i + 1); > // ^ > > > Stream<Number> sn2 = iterate2(0, i -> i < 10, i -> i + 1); // OK > Stream<Number> sn3 = iterate3(0, i -> i < 10, i -> i + 1); // OK > > > Predicate<CharSequence> csNotEmpty = cs -> cs.length() > 0; > > Stream<CharSequence> css1 = iterate1("abcde", csNotEmpty, (String s) > -> s.substring(1)); > > //SignatureTest.java:44: error: method iterate1 in class > SignatureTest cannot be applied to given types; > // Stream<CharSequence> css1 = iterate1("abcde", csNotEmpty, > (String s) -> s.substring(1)); > // ^ > // required: T,Predicate<T>,UnaryOperator<T> > // found: String,Predicate<CharSequence>,(String s)[...]ng(1) > // reason: inference variable T has incompatible equality > constraints String,CharSequence > // where T is a type-variable: > // T extends Object declared in method > <T>iterate1(T,Predicate<T>,UnaryOperator<T>) > > > Stream<CharSequence> css2 = iterate2("abcde", csNotEmpty, (String s) > -> s.substring(1)); > > //SignatureTest.java:54: error: method iterate2 in class > SignatureTest cannot be applied to given types; > // Stream<CharSequence> css2 = iterate2("abcde", csNotEmpty, > (String s) -> s.substring(1)); > // ^ > // required: S,Predicate<S>,UnaryOperator<S> > // found: String,Predicate<CharSequence>,(String s)[...]ng(1) > // reason: inference variable S has incompatible equality > constraints String,CharSequence > // where S,T are type-variables: > // S extends T declared in method > <T,S>iterate2(S,Predicate<S>,UnaryOperator<S>) > // T extends Object declared in method > <T,S>iterate2(S,Predicate<S>,UnaryOperator<S>) > > > Stream<CharSequence> css3 = iterate3("abcde", csNotEmpty, (String s) > -> s.substring(1)); // OK > } > } > > > Regards, Peter > > > > Regards, > Stefan > > > 2016-02-14 15:53 GMT+01:00 Tagir F. Valeev <amae...@gmail.com>: > > Hello! > > I wanted to work on foldLeft, but Brian asked me to take this issue > instead. So here's webrev: > http://cr.openjdk.java.net/~tvaleev/webrev/8072727/r1/ > > I don't like iterator-based Stream source implementations, so I made > them AbstractSpliterator-based. I also implemented manually > forEachRemaining as, I believe, this improves the performance in > non-short-circuiting cases. > > I also decided to keep two flags (started and finished) to track the > state. Currently existing implementation of infinite iterate() does > not use started flag, but instead reads one element ahead for > primitive streams. This seems wrong to me and may even lead to > unexpected exceptions (*). I could get rid of "started" flag for > Stream.iterate() using Streams.NONE, but this would make object > implementation different from primitive implementations. It would also > be possible to keep single three-state variable (byte or int, > NOT_STARTED, STARTED, FINISHED), but I doubt that this would improve > the performance or footprint. Having two flags looks more readable to > me. > > Currently existing two-arg iterate methods can now be expressed as a > partial case of the new method: > > public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) { > return iterate(seed, x -> true, f); > } > (same for primitive streams). I may do this if you think it's > reasonable. > > I created new test class and added new iterate sources to existing > data providers. > > Please review and sponsor! > > With best regards, > Tagir Valeev. > > (*) Consider the following code: > > int[] data = {1,2,3,4,-1}; > IntStream.iterate(0, x -> data[x]) > .takeWhile(x -> x >= 0) > .forEach(System.out::println); > > Currently this unexpectedly throws an AIOOBE, because > IntStream.iterate unnecessarily tries to read one element ahead. > >