Comment #0 by bearophile_hugs — 2014-01-13T04:44:56Z
void main() nothrow {
import std.algorithm: zip;
int[] a;
foreach (p; zip(a, a)) {}
}
dmd 2.065alpha gives:
temp.d(4): Error: 'std.range.Zip!(int[], int[]).Zip.empty' is not nothrow
temp.d(4): Error: 'std.range.Zip!(int[], int[]).Zip.popFront' is not nothrow
temp.d(1): Error: function 'D main' is nothrow yet may throw
The signature of zip is:
auto zip(Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges));
auto zip(Ranges...)(StoppingPolicy sp, Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges));
The empty() method of Zip:
@property bool empty() {
import std.exception : enforce;
final switch (stoppingPolicy) {
case StoppingPolicy.shortest:
foreach (i, Unused; R)
if (ranges[i].empty) return true;
return false;
case StoppingPolicy.longest:
foreach (i, Unused; R)
if (!ranges[i].empty) return false;
return true;
case StoppingPolicy.requireSameLength:
foreach (i, Unused; R[1 .. $])
enforce(ranges[0].empty ==
ranges[i + 1].empty,
"Inequal-length ranges passed to Zip");
return ranges[0].empty;
}
assert(false);
}
The case StoppingPolicy.requireSameLength can throw, so zip can't be nothrow.
But with a different API:
auto zip(StoppingPolicy = StoppingPolicy.requireSameLength, Ranges...)(Ranges ranges)
You can use a "static if" inside Zip to tell apart the various cases (because D doesn't have a static switch), allowing most times zip to be usable inside nothrow functions.
Comment #1 by monarchdodra — 2014-03-18T03:21:11Z
AFAIK, requireSameLength shouldn't be throwing exceptions to begin with. So this can probably be solved without changing the API.
Triggering the enforce requires calling popFront on an empty Zip, which is illegal to begin with.
Comment #2 by monarchdodra — 2014-04-25T15:10:51Z
Duplicate of 11319.
BTW, "std.algorithm: zip".
We really need to get rid of the conditional global imports.
*** This issue has been marked as a duplicate of issue 11319 ***