foreach vs. iterators
BCS
BCS at pathlink.com
Mon Nov 6 09:46:17 PST 2006
Sean Kelly wrote:
> Walter Bright wrote:
>
>> Sean Kelly wrote:
>>
>>> I think I agree, but for the sake of argument, how would D handle
>>> 'find' operations on sequences that don't support opIndex? At some
>>> point, a generalizable bookmark is almost necessary for a faithful
>>> implementation of some C++ algorithms. Also, many of these
>>> algorithms also require iteration across two sequences
>>> simultaneously, which doesn't map very cleanly into foreach.
>>> Consider a substring-style find operation (std::search), for example,
>>> where both the pattern and target types do not support opIndex or
>>> opSlice. I might argue that it's a bit silly or unrealistic to
>>> desire such an operation, but the C++ algorithm library does support it.
>>
>>
>> I think the target types will have to support opIndex or opSlice.
>
>
> Forgive me for resurrecting a horribly battered equine, but I was
> thinking about this a bit tonight and I've decided that foreach,
> foreach_reverse, and array operations are not a sufficient general
> substitute for C++ iterators.
>
> For example, let's say I want to compute the set union of two sorted
> ranges, one of size M, the other of size N. By iterating across the two
> ranges simultaneously is is easy to see that the complexity for the
> operation will be max(M,N). In C++ this is easily accomplished using
> forward iterators, and the ranges can be anything from arrays to SQL
> result sets.
>
> In D however, there is no way to iterate across multiple ranges
> simultaneously using foreach, so opIndex must be used instead. With
> containers that have a constant-time lookup cost this isn't a big deal,
> but what if these containers are binary trees? The complexity for such
> an operation would be M(log(M)) + N(log(N)).
>
> From this it seems clear that foreach is not sufficiently adaptable to
> meet the needs of all sequential algorithms and opIndex is not a
> reasonable substitute for all cases where foreach may not be used. What
> alternatives do we have? So far, iterator variants are all I've been
> able to come up with.
>
>
> Sean
I have created a monster!!!
// a class that can iterate over it's contents and another
// iterator's contents in order
class Foo
{
// return an iterator
int delegate(int delegate(inout U))
opApplyWith(int delegate(inout U) t)
{
// make a class to form delegate
auto ret = new class
{
// context
int delegate(inout U) t;
// iterator
int ret(int delegate(inout U) dg)
{
int i=0;
// loop on other
foreach(inout U u, t)
{
// sub loop on self
while(i<sortedUs.length && sortedUs[i] < u)
if(int r = dg(sortedUs[i++])) return r;
if(int r = dg(u)) return r;
}
}
};
// set context
ret.t = t;
// return it
return &ret.ret;
}
// loop on self only
int opApply(int delegate(inout U) dg)
{
foreach(inout U u, sortedUs)
{
if(int r = dg(sortedUs[i++])) return r;
}
}
// data for class
U[] sortedUs;
}
// use it.
int main()
{
Foo f1, f2;
foreach(U u; f1.opApplyWith(&f2.opApply))
{
use(u);
}
}
More information about the Digitalmars-d-announce
mailing list