www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opApply safety

reply Chris Wright <dhasenan gmail.com> writes:
I want to create an opApply for a type.

I've marked my code  safe, because everything I wrote was  safe. The body 
of opApply is  safe, but it calls a delegate that may or may not be  safe.

How do I make it so I can iterate through this type safely and systemly?

I want to support iteration like:

foreach (string key, string value; collection) {}
foreach (size_t i, string key, string value; collection) {}
Jan 29
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/29/16 12:44 PM, Chris Wright wrote:
 I want to create an opApply for a type.

 I've marked my code  safe, because everything I wrote was  safe. The body
 of opApply is  safe, but it calls a delegate that may or may not be  safe.

 How do I make it so I can iterate through this type safely and systemly?
Likely an overload. Tag the delegate as being safe or not. -Steve
Jan 29
parent reply Chris Wright <dhasenan gmail.com> writes:
On Fri, 29 Jan 2016 14:00:08 -0500, Steven Schveighoffer wrote:

 On 1/29/16 12:44 PM, Chris Wright wrote:
 I want to create an opApply for a type.

 I've marked my code  safe, because everything I wrote was  safe. The
 body of opApply is  safe, but it calls a delegate that may or may not
 be  safe.

 How do I make it so I can iterate through this type safely and
 systemly?
Likely an overload. Tag the delegate as being safe or not. -Steve
That's handy. It works. I can make it so someone can call: foo.opApply((i, k, v) safe => 0); foo.opApply((i, k, v) system => 0); And that works. However, if you have: safe void bar() { foreach(i, k, v; foo) { } } the compiler complains: opapplysafe.d(12): Error: foo.opApply matches more than one declaration: opapplysafe.d(2): safe int(int delegate(int, string, string) safe dg) and: opapplysafe.d(5): system int(int delegate(int, string, string) system dg) Guess I'll file a bug.
Jan 29
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/29/16 3:08 PM, Chris Wright wrote:
 On Fri, 29 Jan 2016 14:00:08 -0500, Steven Schveighoffer wrote:

 On 1/29/16 12:44 PM, Chris Wright wrote:
 I want to create an opApply for a type.

 I've marked my code  safe, because everything I wrote was  safe. The
 body of opApply is  safe, but it calls a delegate that may or may not
 be  safe.

 How do I make it so I can iterate through this type safely and
 systemly?
Likely an overload. Tag the delegate as being safe or not. -Steve
That's handy. It works. I can make it so someone can call: foo.opApply((i, k, v) safe => 0); foo.opApply((i, k, v) system => 0); And that works. However, if you have: safe void bar() { foreach(i, k, v; foo) { } } the compiler complains: opapplysafe.d(12): Error: foo.opApply matches more than one declaration: opapplysafe.d(2): safe int(int delegate(int, string, string) safe dg) and: opapplysafe.d(5): system int(int delegate(int, string, string) system dg) Guess I'll file a bug.
Definitely seems like a bug. As a workaround, you can name the opApply functions: struct S { int opApply(int delegate(int, string, string) safe dg) safe {...} int unsafeApply(int delegate(int, string, string) dg) {...} } foreach(i, k, v; foo.unsafeApply) {...} though that's... ugly. -Steve
Jan 29
prev sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Friday, 29 January 2016 at 17:44:34 UTC, Chris Wright wrote:
 I want to create an opApply for a type.

 I've marked my code  safe, because everything I wrote was 
  safe. The body of opApply is  safe, but it calls a delegate 
 that may or may not be  safe.

 How do I make it so I can iterate through this type safely and 
 systemly?

 I want to support iteration like:

 foreach (string key, string value; collection) {}
 foreach (size_t i, string key, string value; collection) {}
You can implement an input range and annotate all the primitives as safe. Then if there's only an input range in your agregate, DMD will auto-detect that it must use it in foreach(): http://dlang.org/spec/statement.html#foreach-with-ranges in the worst case (range not implementable directly but only as a getter in .range() or .opSlice() you'll have to change the style a bit and consume the range explicitly in a typical "while (!stuff.empty) {...}"
Jan 29
parent Chris Wright <dhasenan gmail.com> writes:
On Fri, 29 Jan 2016 23:35:35 +0000, Basile B. wrote:
 You can implement an input range and annotate all the primitives as
  safe.
I hadn't realized that if front() returns a tuple, it's automatically expanded. Works for me.
Jan 29