Continue iteration after exception

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Jan 23 08:09:01 PST 2013


On Wed, Jan 23, 2013 at 04:52:25PM +0100, monarch_dodra wrote:
> On Wednesday, 23 January 2013 at 15:24:02 UTC, Josh wrote:
> >On Wednesday, 23 January 2013 at 15:00:16 UTC, bearophile wrote:
> >>A possible solution: desugar the foreach range iteration
> >>protocol of dirEntries and wrap the relevant method with a
> >>try-catch.
> >
> >Sorry, could you explain that a little? I'm not sure what desugar
> >means :/
> 
> He means you turn it into a normal loop with !empty, front and
> popFront.

This may not be possible if DirEntries is implemented with opApply
instead of a range.

Anyway, since I don't think everyone is aware of what opApply is or what
a range is, here's a (very) brief explanation:

In D, foreach loops can work with any user-defined type as long as they
either (1) provide a method called "opApply", or (2) implement a range
interface, that is, the methods "empty", "front", and "popFront".

The method opApply looks like this:

	int opApply(scope int delegate(X...) dg) { ... }

where X... represents the loop counter(s). For instance, if you want to
support:

	foreach (int x, int y; obj) { ... }

then opApply should look like:

	int opApply(scope int delegate(ref int x, ref int y) dg) { ... }

The idea is that opApply will iterate over the contents of the object
and call the delegate dg with each value (or set of values).

Alternatively, the object can implement the range interface, which will
also allow it to be used with std.algorithm and a whole bunch of other
cool stuff. The minimal range interface requires the object to define
the following methods:

	@property bool empty() {...} // return true if there are no more elements
	@property T front() {...} // return the current element
	void popFront() {...} // move to the next element

The compiler then translates ("lowers") a loop like:

	foreach (x; obj) { do_something(x); }

into:

	while (!obj.empty) {
		do_something(obj.front);
		obj.popFront();
	}

Hope this is helpful.


> That wouldn't really work anyways. Why you'd be able to catch the
> exception when calling popFront, and preserve your iteration state,
> you'd be unable to iterate past the exception point :/

Yeah, I think we might need an enhancement request to add a flag to
ignore access errors while traversing the filesystem.


T

-- 
Latin's a dead language, as dead as can be; it killed off all the
Romans, and now it's killing me! -- Schoolboy


More information about the Digitalmars-d-learn mailing list