www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Continue iteration after exception

reply "Josh" <moonburntm gmail.com> writes:
DMD 2.060, Windows 7 64-bit

Source:

import std.file;
import std.stdio;

void main()
{
     foreach (DirEntry d; dirEntries("C:\\", SpanMode.breadth))
         writeln(d.name);
}

This code stops with "std.file.FileException std\file.d(2434): 
C:\Documents and Settings: Access is denied." when it gets to 
C:\Documents and Settings. On Windows 7 that doesn't actually 
exist, which is fine. What I'd like it to do is tell me that it 
doesn't exist, but continue iterating anyway. I've tried 
try-catch, but that just stops the iteration.

Any help is appreciated. Thanks :)

Josh
Jan 23 2013
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Josh:

 Any help is appreciated. Thanks :)
A possible solution: desugar the foreach range iteration protocol of dirEntries and wrap the relevant method with a try-catch. Bye, bearophile
Jan 23 2013
parent reply "Josh" <moonburntm gmail.com> writes:
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 :/
Jan 23 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
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. 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 :/
Jan 23 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Jan 23 2013
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 23 January 2013 at 16:10:57 UTC, H. S. Teoh wrote:
 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.
[SNIP]
 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
As a workaround, one can manually and recursively iterate the files with a "shallow" span. The result would be a depth first iteration. //---- void foo(string s) { writeln(s); if (!s.isDir()) return; try { foreach(string dir; dirEntries(s, SpanMode.shallow)) { foo(dir); } } catch {} } void main() { foo(`C:\\`); } //----
Jan 23 2013
prev sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
23-Jan-2013 20:09, H. S. Teoh пишет:
 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.
It's a range. TL;DR :) -- Dmitry Olshansky
Jan 23 2013