> -----Original Message-----
> From: Andy Seaborne [mailto:[email protected]]
> Sent: Tuesday, September 27, 2011 4:56 AM
> To: [email protected]
> Subject: Iter.mapMany
>
> Stephen,
>
> I took the liberty of rewriting the implementation of Iter.mapMany - it
> didn't cope with the case where one of the sub-iterators returned was
> zerolength because it created the iterator and immediately called
> .next().
>
> The situation occurred in the SPARQL WG test suite for Update, where a
> binding didn't generate any legal quads.(TemplateLib.calcQuads).
>
Sounds good. Not enough tests I guess!
>
> Where did the name "mapMany" come from? It's called "flatMap in scala.
>
I called it "mapMany", because I was used to the equivalent C# LINQ operator
called "SelectMany" [1]. LINQ's version of "Select" is called "map" in ARQ, so
I went with "mapMany".
> The implement of flatmap is shorter :-) ... and recursive (the while
> loop in mapMany is removing that tail recursion).
>
> Andy
>
> scala.collection.Iterator[A]
>
> def flatMap[B](f: A => GenTraversableOnce[B]): Iterator[B]
> = new Iterator[B] {
> private var cur: Iterator[B] = empty
> def hasNext: Boolean =
> cur.hasNext || self.hasNext &&
> { cur = f(self.next).toIterator; hasNext }
> def next(): B = (if (hasNext) cur else empty).next()
> }
Oh, to have optimized tail recursion in Java! We can hope it arrives soon.
Incidentally, I find C#'s implementation even more elegant (argument checking
elided):
public static IEnumerable<TResult> SelectMany<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector)
{
foreach (TSource item in source)
{
foreach (TResult result in selector(item))
{
yield return result;
}
}
}
This relies on C#'s yield generator [2], which makes creating iterators so much
simpler!
-Steve
[1] http://msdn.microsoft.com/en-us/library/bb534336.aspx
[2] http://msdn.microsoft.com/en-us/library/9k7k7cf0(v=VS.100).aspx