www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach on const(V[K])

reply "Dan" <dbdavidson yahoo.com> writes:
I posted this on *learn* a few days back.
Is this a reasonable language request - to allow for ref of 
immutable(K) on associative array iteration? If allowed it would 
enable iteration without casting, because casting could allow for 
unintended consequences. Maybe there is another way?

The original is at this link and contents are copied below.
http://forum.dlang.org/post/rxobffxfqbqotyhmrznf forum.dlang.org

Thanks
Dan


Wouldn't a better form for foreach on associative arrays be one
of:

*case 1*
foreach(ref immutable(K) k; ref V v) {
}

*case 2*
foreach(ref immutable(K) k; ref const(V) v) {
}

Both of these would allow for iterating over const associative
arrays without *copying* the key K. As it stands you can not
iterate, or even get the length (which under the covers does
iteration) of a const(V[K]) without casting off const deeply
because the foreach approach is to copy the keys. But it should
not need to? Couldn't it allow a reference to the keys and the
type on iteration of the key should be immutable.

In the example below casting is the only way to get at length and
on the iteration the keys are (needlessly?) copied.

Thanks,
Dan

--------- OUTPUT -----------
Length:
1
Foreach:
Key dupped
k => a val => b
-----------------------------------------------------------------
import std.stdio;
const int asPreferred = 0;
struct Key {
   this(this){ c=c.dup; writeln("Key dupped"); }
   char[] c;
}
struct Val {
   this(this){ c=c.dup; writeln("Val dupped"); }
   char[] c;
}
alias Val[Key] Map;
void foo(ref const(Map) m) {
   static if(asPreferred) {
     writeln(m.length);
     foreach(ref immutable(K) k, ref const(Val) v; m) {}
   } else {
     writeln("Length:");
     writeln((cast(Val[Key])m).length);
     writeln("Foreach:");
     foreach(k,ref Val v; cast(Val[Key])m) {
       writeln("k => ", k.c, " val => ", v.c);
     }
   }
}

void main() {
   Val[Key] aa = [ Key(['a']) : Val(['b']) ];
   foo(aa);
}
Nov 19 2012
next sibling parent reply "Dan" <dbdavidson yahoo.com> writes:
On Monday, 19 November 2012 at 12:24:56 UTC, Dan wrote:
 I posted this on *learn* a few days back.
 Is this a reasonable language request - to allow for ref of 
 immutable(K) on associative array iteration? If allowed it 
 would enable iteration without casting, because casting could 
 allow for unintended consequences. Maybe there is another way?

 The original is at this link and contents are copied below.
 http://forum.dlang.org/post/rxobffxfqbqotyhmrznf forum.dlang.org

 Thanks
 Dan


 Wouldn't a better form for foreach on associative arrays be one
 of:

 *case 1*
 foreach(ref immutable(K) k; ref V v) {
 }

 *case 2*
 foreach(ref immutable(K) k; ref const(V) v) {
 }

 Both of these would allow for iterating over const associative
 arrays without *copying* the key K. As it stands you can not
 iterate, or even get the length (which under the covers does
 iteration) of a const(V[K]) without casting off const deeply
 because the foreach approach is to copy the keys. But it should
 not need to? Couldn't it allow a reference to the keys and the
 type on iteration of the key should be immutable.

 In the example below casting is the only way to get at length 
 and
 on the iteration the keys are (needlessly?) copied.

 Thanks,
 Dan

 --------- OUTPUT -----------
 Length:
 1
 Foreach:
 Key dupped
 k => a val => b
 -----------------------------------------------------------------
 import std.stdio;
 const int asPreferred = 0;
 struct Key {
   this(this){ c=c.dup; writeln("Key dupped"); }
   char[] c;
 }
 struct Val {
   this(this){ c=c.dup; writeln("Val dupped"); }
   char[] c;
 }
 alias Val[Key] Map;
 void foo(ref const(Map) m) {
   static if(asPreferred) {
     writeln(m.length);
     foreach(ref immutable(K) k, ref const(Val) v; m) {}
   } else {
     writeln("Length:");
     writeln((cast(Val[Key])m).length);
     writeln("Foreach:");
     foreach(k,ref Val v; cast(Val[Key])m) {
       writeln("k => ", k.c, " val => ", v.c);
     }
   }
 }

 void main() {
   Val[Key] aa = [ Key(['a']) : Val(['b']) ];
   foo(aa);
 }

At the risk of being too persistent ... are there any opinions on this? It seems a small tweak to the meaning of foreach with associative arrays would fix some issues requiring unnecessary casts. It should also be more efficient as there would be no need for extra copying of keys. Thanks Dan
Nov 27 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/27/12 10:32 AM, Dan wrote:
 At the risk of being too persistent ... are there any opinions on this?
 It seems a small tweak to the meaning of foreach with associative arrays
 would fix some issues requiring unnecessary casts. It should also be
 more efficient as there would be no need for extra copying of keys.

As far as I understand you reveal it's impossible to iterate a const(V[K]), which is an implementation bug. Please file it with bugzilla. Thanks, Andrei
Nov 27 2012
prev sibling next sibling parent "Dan" <dbdavidson yahoo.com> writes:
On Tuesday, 27 November 2012 at 16:08:54 UTC, Andrei Alexandrescu 
wrote:
 As far as I understand you reveal it's impossible to iterate a 
 const(V[K]), which is an implementation bug. Please file it 
 with bugzilla.

Sure I will do that as I think it is impossible without a deep cast. But, I don't know that it is an implementation bug as much as a incorrect definition of the foreach per the langauge spec. From 'Foreach over Associative Arrays': "The type of the variable must match the type of the array contents. If there are two variables declared, the first is said to be the index and the second is said to be the value. The index must be of the same type as the indexing type of the associative array. It cannot be ref, and it is set to be the index of the array element." I do not understand why "it cannot be ref" and am suggesting that that should say and be implemented as rather: "it is naturally a ref, whether you include the ref keyword or not and in fact it is ref const(K). This way we could do: foreach(k, ref v; aa) { } when aa is a const(V[K]).
Nov 27 2012
prev sibling parent "Dan" <dbdavidson yahoo.com> writes:
On Tuesday, 27 November 2012 at 16:08:54 UTC, Andrei Alexandrescu 
wrote:
 On 11/27/12 10:32 AM, Dan wrote:
 At the risk of being too persistent ... are there any opinions 
 on this?
 It seems a small tweak to the meaning of foreach with 
 associative arrays
 would fix some issues requiring unnecessary casts. It should 
 also be
 more efficient as there would be no need for extra copying of 
 keys.

As far as I understand you reveal it's impossible to iterate a const(V[K]), which is an implementation bug. Please file it with bugzilla. Thanks, Andrie

http://d.puremagic.com/issues/show_bug.cgi?id=9085
Nov 27 2012