Internal and External truncation conditions
zhong.j.yu at gmail.com
Sat Feb 9 20:59:10 PST 2013
On Sat, Feb 9, 2013 at 10:25 PM, Zhong Yu <zhong.j.yu at gmail.com> wrote:
> Based on my own use cases, code that needs forEachUntil() usually
> intends to process just enough elements to produce a result, for
> example, a lexer scans a char stream until it yields a token. In that
> sense forEachUntil() is really an aggregator for *some* elements. We
> may have a method in the form of
> interface Stream<T>
> <R> R scan(Function<T,R> scanner)
> The scanner is usually stateful. Elements are fed to the scanner,
> until it returns a non-null value; that value is the return value of
> scan(). If end of stream is reached before scanner returns non-null,
> scan() returns null. A scanner may need to react to EOF event, the
> application can design an EOF sentinel of type T.
> In the parallel case, scanner must be thread-safe; if it returns
> non-null for one split, it should return non-null for all splits at
> around the same time; one of the non-null values is chosen arbitrarily
> as the result of scan().
> If null sentinel is too distasteful, scanner can return Optional<R>;
> or it can yield result into a Consumer<R> sink.
> Collection<Int> primes = ints.parallel().scan( gather primes till xxx );
> Paragraph para = lines.scan( gather lines till an empty line or EOF );
> scan() is only intended for part of the stream. To turn the whole
> stream into another stream, say a line stream into a paragraph stream,
> flatMap(FlatMapper) should work just fine.
Actually, scan() can be defined in term of
the mapper is stateful; it gathers some elements then yields a result
to the sink.
The scan() method, though providing the same functionality, is more
clear about the intention of the programmer.
More information about the lambda-libs-spec-observers