Stream generators

Joe Bowbeer joe.bowbeer at gmail.com
Fri Nov 30 12:38:16 PST 2012


Here are two examples of methods that combine two streams:

1. An addStreams method, like the one below written in Python that
generates a stream by summing two other streams:

    def addStreams(si, sj): # add corres. elements of two streams
        if not si: return sj
        if not sj: return si
        tailsum = lambda ti=si, tj=sj : addStreams(tail(ti), tail(tj))
        return (head(si) + head(sj), tailsum)

Source:

http://code.activestate.com/lists/python-list/9029/


2. A merge method, like the one below written in Scala that generates
Hamming numbers:

  def hamming: Stream[Int] =
    Stream.cons(1, merge(hamming.map(2*), merge(hamming.map(3*),
hamming.map(5*))))

Where the merge method is defined:

  def merge[T](a: Stream[T], b: Stream[T])(implicit ord: Ordering[T]):
Stream[T] = {
    if (b.isEmpty)
      a
    else if (a.isEmpty)
      b
    else {
      val order = ord.compare(a.head, b.head)
      if (order < 0)
        Stream.cons(a.head, merge(a.tail, b))
      else if (order > 0)
        Stream.cons(b.head, merge(a, b.tail))
      else
        Stream.cons(a.head, merge(a.tail, b.tail))
    }
  }

Source:

http://code.google.com/p/wing-ding/source/browse/trunk/books/Programming_Scala/src/adhoc/HammingNumbers/src/hamming/Main.scala


Is it easy to write the corresponding methods in Java?

Joe



On Fri, Nov 30, 2012 at 10:09 AM, Joe Bowbeer <joe.bowbeer at gmail.com> wrote:

> I mean a more general merge which may emit an element from either stream,
> depending, and may drop some elements from one or both streams.
> On Nov 30, 2012 9:51 AM, "Brian Goetz" <brian.goetz at oracle.com> wrote:
>
>>  I think it would be beneficial for comparison to show a bit of their
>>> implementations.
>>>
>>
>> Here's iterate(seed, UnaryOperator):
>>
>>     public static<T> Stream<T> iterate(final T seed, final
>> UnaryOperator<T> f) {
>>         Objects.requireNonNull(f);
>>         final InfiniteIterator<T> iterator = new InfiniteIterator<T>() {
>>             T t = null;
>>
>>             @Override
>>             public T next() {
>>                 return t = (t == null) ? seed : f.operate(t);
>>             }
>>         };
>>         return stream(new StreamSource.ForIterator<>(**iterator),
>> StreamOpFlag.IS_ORDERED);
>>     }
>>
>> Not too difficult.  But, the idea is to make things that are easy in the
>> header of a for-loop to be easy as the source of a stream.
>>
>>  repeat(n) in Scheme is about 10 characters.
>>>
>>
>> Yeah, well this is Java...
>>
>>  How difficult is it to implement a merge, as might be needed to generate
>>> Hamming numbers? (One of my favorite test cases.)
>>>
>>
>> You mean, interleave two streams?  That's on our list to implement as
>> Streams.interleave(a, b).
>>
>>  Is there a method to limit a stream to a length?  If so then one of your
>>> methods may be extra baggage.
>>>
>>
>> Yes: stream.limit(n).
>>
>>


More information about the lambda-libs-spec-observers mailing list