Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
January 23, 2013 Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
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 |
January 23, 2013 Re: Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
Posted in reply to Josh | 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
|
January 23, 2013 Re: Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | 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 :/
|
January 23, 2013 Re: Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
Posted in reply to Josh | 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 :/
|
January 23, 2013 Re: Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 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 |
January 23, 2013 Re: Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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:\\`);
}
//----
|
January 23, 2013 Re: Continue iteration after exception | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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 |
Copyright © 1999-2021 by the D Language Foundation