Automatic Foreach

janderson askme at me.com
Sat Apr 26 23:45:36 PDT 2008


I know Walter has his head stuck in Const/Invarient/Pure multithreading 
land at the moment.  I thought I'd fire off this interesting proposal 
anyway.

This is a follow up proposal/suggestion to one I sent a while back.  I 
hope to flesh it out a bit more.

The idea is to automatically generate for loops for arrays that are used 
as parameters.  It will reduces type safety in one area but makes the 
language more expressive, particularly for templates.

Basically:

void foo(char c)
{
  ...
}

...

char[] array;

...

This part:

foreach(auto value; array)
{
   foo(array);
}

becomes:

foo(array);


More advanced stuff:

//////////////////////////////////////////////////
//Example 1
//////////////////////////////////////////////////
// The return value is called multiple times:

float[] array;
array ~= sqrt(array2);

Where sqrt is:

float sqrt(float value);

Would be equivalent to:

int i = array.length;
array.length += array2.length;
foreach(auto val; array2)
{
   array[i++] = sqrt(val);
}

//////////////////////////////////////////////////
//Example 2
//////////////////////////////////////////////////
// When assigned to an array, that array should automatically be resized 
to the number of iterations the function is be called.

float[] array = sqrt(array2);  //array is resized to the correct size

Would be equivalent to:

float[] array;
array.length = array2.length;
int i = 0;
foreach(auto val; array2)
{
   array[i++] = sqrt(val);
}

//////////////////////////////////////////////////
//Example 3
//////////////////////////////////////////////////
// Multiple array inputs should work like nested arrays.

vector[] vertex = dot(array1, array2);

Equivalent too:

vector[] vertex;
vector.length = array1.length * array2.length;
int i=0;
foreach (auto val1; array1)
{
   foreach (auto val2; array2)
   {
     vertex[i++] = sqrt(val1, val2);
   }
}

//////////////////////////////////////////////////
//Example Member functions
//////////////////////////////////////////////////
// This is potentially less useful and could be made illegal.  I'll 
mention it for completeness.

class A
{
   void foo();
}

...

A[] a;

...

a.foo();  //Call foo for the length of a


Equivalent to:

foreach (auto val; a)
{
    a.foo();
}

//////////////////////////////////////////////////
//Example Return types
//////////////////////////////////////////////////

proccess(array).foo().foo2();

Equivalent too:

foreach (auto val; )
{
   proccess(val).foo().foo2();
}

//////////////////////////////////////////////////
//Use example nested
//////////////////////////////////////////////////


results ~= func(foo(array1), foo2(array2));

Equivalent too:

results.length += array1.length * array2.length;
int i = results.length;
foreach (auto val1; array1)
{
   foreach (auto val2; array2)
   {
      results[i++] = func(foo(val1), foo2(val2));
   }
}


//////////////////////////////////////////////////
//Use example
//////////////////////////////////////////////////

results ~= func(foo(array1)).method(array2);

results.length += array1.length * array2.length;
int i = results.length;
foreach (auto val1; array1)
{
   foreach (auto val2; array2)
   {
      results[i++] = func(foo(val1)).method(val2);
   }
}

//////////////////////////////////////////////////
//Use example with templates
//////////////////////////////////////////////////

void print(A ...)(A a)
{
   write(a);
}

print(array1, array2, value);

//What happens here is the array is passed into the template, because an 
array is a valid input into a template.  The value is only evaluated 
when inside the template. See overloading rules below.

So it's equivalent to:

foreach (auto val; array1)
{
   write(val);
}

foreach (auto val; array2)
{
   write(val);
}

Overloading rules:

This auto foreach is given the lowest priority.  If there's already a 
way to call the function then that will be used.  That will enable 
people to specialize how arrays are handled for different functions be 
overloading it.  Templates for example, an array is a valid input so it 
won't call the template function multiple times.

Working with the future:
The proposal should work well with features such as pure functions.  It 
should be as optimal as foreach statements however the compiler would 
have to do less work to realize optimizations.

Interchangeable methods/functions: If this feature comes in, I don't see 
any problem with the proposal working.

Rantional:
Half the time I create a for loop I endup encapsulating it in a 
function.  If D automatically created the function it would be one less 
thing to worry about.  If I need specialize behavior I could always 
specialize the function later by providing an overload.

I think having this functionality would remove much of the need for 
being able to iterate over 2 arrays at the same time.

Comment:
I know python has syntax not unlike this, however I believe the above is 
even simpler.

What do you think?



More information about the Digitalmars-d mailing list