www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - for, foreach identifier allowed in c throws error in d

reply "Logesh Pillay" <lp.court.jester gmail.com> writes:
It is common in a recursive function to amend a global array 
using the function parameter to refer to the element eg

int[10];

void foo (int i) {
   foreach (x; 0 .. 9) {
      t[i] = x;
      foo ();

C in a for loop allows use of t[i] directly as the iterating 
variable so you don't need the dummy variable x which has no real 
function.

D does not.  The error generated is "no identifier for declarator 
t[i]". For a long time, I thought that was specific to foreach 
but the same thing happens with for.

It looks like an unnecessary restriction.  Am I missing something?
Jun 02 2014
next sibling parent "Logesh Pillay" <lp.court.jester gmail.com> writes:
Of course, in the first line I meant to say
int[10] t;
Jun 02 2014
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 02 Jun 2014 15:21:06 -0400, Logesh Pillay  
<lp.court.jester gmail.com> wrote:

 It is common in a recursive function to amend a global array using the  
 function parameter to refer to the element eg

 int[10];

 void foo (int i) {
    foreach (x; 0 .. 9) {
       t[i] = x;
       foo ();

 C in a for loop allows use of t[i] directly as the iterating variable so  
 you don't need the dummy variable x which has no real function.

 D does not.  The error generated is "no identifier for declarator t[i]".  
 For a long time, I thought that was specific to foreach but the same  
 thing happens with for.

 It looks like an unnecessary restriction.  Am I missing something?
Can you post a full compiling example? I can't figure out what you are trying to do with this code. -Steve
Jun 02 2014
parent reply "Logesh Pillay" <lp.court.jester gmail.com> writes:
Issue has nothing to do with recursion.  That's only where I keep 
seeing it.

eg a function to generate combinations.

import std.stdio;

int[3] t;

void foo (int i) {
   if (i == 3)
     writef("%s\n", t);
   else foreach (x; 0 .. 3) {
     t[i] = x;
     foo(i+1);
   }
}

void main() {
   foo(0);
}

In C, I could put in the equivalent for statement for foreach, 
t[i] as the iterating variable. I won't need x which exists as a 
middleman only and save myself two lines.
Jun 02 2014
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 02 Jun 2014 15:47:02 -0400, Logesh Pillay  
<lp.court.jester gmail.com> wrote:

 Issue has nothing to do with recursion.  That's only where I keep seeing  
 it.

 eg a function to generate combinations.

 import std.stdio;

 int[3] t;

 void foo (int i) {
    if (i == 3)
      writef("%s\n", t);
    else foreach (x; 0 .. 3) {
      t[i] = x;
      foo(i+1);
    }
 }

 void main() {
    foo(0);
 }

 In C, I could put in the equivalent for statement for foreach, t[i] as  
 the iterating variable. I won't need x which exists as a middleman only  
 and save myself two lines.
OK, I get it. You want to do: foreach(t[i]; 0 .. 3) But this doesn't work. This should (the equivalent for C): for(t[i] = 0; t[i] < 3; ++t[i]) I'm trying to think of a way to do this without loops, but not sure. Note that foreach is expected to be given a new variable to declare, so you can't foreach with an existing variable on the left. -Steve
Jun 02 2014
next sibling parent "Logesh Pillay" <lp.court.jester gmail.com> writes:
Sorry, I am embarassed to say I've just tried the for equivalent 
and it works with t[i] as the iterating variable.

import std.stdio;

int[3] t;

void foo (int i) {
   if (i == 3)
     writef("%s\n", t);
   else for (t[i] = 0; t[i] < 3; t[i]++)
     foo(i+1);
}

void main() {
   foo(0);
}

Sorry, yet another overhasty post
Jun 02 2014
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 02 Jun 2014 15:58:01 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:


 I'm trying to think of a way to do this without loops, but not sure.
I'm surprised, I looked for some kind of "apply" function like map, but just calls some function with each element in the range. Something like this would make this a 1 (2?) liner: if(i == t.length) writeln(t) else each!((x) => {t[i] = x; foo(i+1);})(iota(x.length)); But I can't find a phobos primitive for each. Would have expected it in std.algorithm or std.functional? -Steve
Jun 02 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 2 June 2014 at 20:23:12 UTC, Steven Schveighoffer 
wrote:
 On Mon, 02 Jun 2014 15:58:01 -0400, Steven Schveighoffer 
 <schveiguy yahoo.com> wrote:


 I'm trying to think of a way to do this without loops, but not 
 sure.
I'm surprised, I looked for some kind of "apply" function like map, but just calls some function with each element in the range. Something like this would make this a 1 (2?) liner: if(i == t.length) writeln(t) else each!((x) => {t[i] = x; foo(i+1);})(iota(x.length)); But I can't find a phobos primitive for each. Would have expected it in std.algorithm or std.functional? -Steve
Its been discussed a few times. There were some objections (IIRC Walter thought that there was no significant advantage over plain foreach).
Jun 02 2014
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 02 Jun 2014 17:25:24 -0400, John Colvin  
<john.loughran.colvin gmail.com> wrote:

 On Monday, 2 June 2014 at 20:23:12 UTC, Steven Schveighoffer wrote:
 On Mon, 02 Jun 2014 15:58:01 -0400, Steven Schveighoffer  
 <schveiguy yahoo.com> wrote:


 I'm trying to think of a way to do this without loops, but not sure.
I'm surprised, I looked for some kind of "apply" function like map, but just calls some function with each element in the range. Something like this would make this a 1 (2?) liner: if(i == t.length) writeln(t) else each!((x) => {t[i] = x; foo(i+1);})(iota(x.length)); But I can't find a phobos primitive for each. Would have expected it in std.algorithm or std.functional? -Steve
Its been discussed a few times. There were some objections (IIRC Walter thought that there was no significant advantage over plain foreach).
Indeed, foreach is like such a construct: ... else each!((x) {t[i] = x; foo(i+1);})(iota(t.length)); ... else foreach(x; 0 .. t.length) {t[i] = x; foo(i+1);} It's even shorter and clearer. I agree with Walter. Since such a construct by definition wouldn't return anything, you can't chain it. There really is little reason to have it. -Steve
Jun 03 2014
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 3 June 2014 at 13:23:36 UTC, Steven Schveighoffer 
wrote:
 On Mon, 02 Jun 2014 17:25:24 -0400, John Colvin 
 <john.loughran.colvin gmail.com> wrote:

 On Monday, 2 June 2014 at 20:23:12 UTC, Steven Schveighoffer 
 wrote:
 On Mon, 02 Jun 2014 15:58:01 -0400, Steven Schveighoffer 
 <schveiguy yahoo.com> wrote:


 I'm trying to think of a way to do this without loops, but 
 not sure.
I'm surprised, I looked for some kind of "apply" function like map, but just calls some function with each element in the range. Something like this would make this a 1 (2?) liner: if(i == t.length) writeln(t) else each!((x) => {t[i] = x; foo(i+1);})(iota(x.length)); But I can't find a phobos primitive for each. Would have expected it in std.algorithm or std.functional? -Steve
Its been discussed a few times. There were some objections (IIRC Walter thought that there was no significant advantage over plain foreach).
Indeed, foreach is like such a construct: ... else each!((x) {t[i] = x; foo(i+1);})(iota(t.length)); ... else foreach(x; 0 .. t.length) {t[i] = x; foo(i+1);} It's even shorter and clearer. I agree with Walter. Since such a construct by definition wouldn't return anything, you can't chain it. There really is little reason to have it. -Steve
It's more useful like this: import std.algorithm, std.stdio, std.range; template call(Funcs ...) { auto call(T)(T val) { foreach(F; Funcs) { F(val); } return val; } } void doubleIt(ref int i) { i *= 2; } void evalAll(R)(R r) { foreach(v; r){} } void main() { [1,2,3,4].map!(call!(doubleIt, write))().evalAll(); //prints 2468 assert([1,2,3,4].map!(call!doubleIt)().equal([2,4,6,8])); } Eager iteration and mapping functions that don't return anything useful are orthogonal.
Jun 03 2014
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 2 June 2014 at 19:21:07 UTC, Logesh Pillay wrote:
 It is common in a recursive function to amend a global array 
 using the function parameter to refer to the element eg

 int[10];

 void foo (int i) {
   foreach (x; 0 .. 9) {
      t[i] = x;
      foo ();

 C in a for loop allows use of t[i] directly as the iterating 
 variable so you don't need the dummy variable x which has no 
 real function.

 D does not.  The error generated is "no identifier for 
 declarator t[i]". For a long time, I thought that was specific 
 to foreach but the same thing happens with for.

 It looks like an unnecessary restriction.  Am I missing 
 something?
works fine for me: http://dpaste.dzfl.pl/6ff9a3909fde
Jun 02 2014