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?
Something at the back of my mind tells me that, once upon a time,
Walter may have planned something like that for D, whereby
a[] = n;
a[] = b[];
a[] = b[] + c[];
a[] = f(b[]);
would mean
foreach(ref e;a) e = n;
foreach(i,ref e;a) e = b[i];
foreach(i,ref e;a) e = b[i] + c[i];
foreach(i,ref e;a) e = f(b[i]);
respectively. But if so, the plan got dropped a long time ago, and now
only the first two cases work.
(Disclaimer: I may have got that completely wrong).
I don't see the problem with the foreach version though. It's
certainly transparent.
Apr 27 2008
↑ ↓← → Bill Baxter <dnewsgroup billbaxter.com> writes:
Janice Caron wrote:
Something at the back of my mind tells me
Maybe its the compiler error message that says "vector operations are
not implemented" that's telling you that. :-) (as opposed to just
plain "syntax error")
that, once upon a time,
Walter may have planned something like that for D, whereby
a[] = n;
a[] = b[];
a[] = b[] + c[];
a[] = f(b[]);
would mean
foreach(ref e;a) e = n;
foreach(i,ref e;a) e = b[i];
foreach(i,ref e;a) e = b[i] + c[i];
foreach(i,ref e;a) e = f(b[i]);
respectively. But if so, the plan got dropped a long time ago, and now
only the first two cases work.
(Disclaimer: I may have got that completely wrong).
I don't see the problem with the foreach version though. It's
certainly transparent.
Something at the back of my mind tells me that, once upon a time,
Walter may have planned something like that for D, whereby
a[] = n;
a[] = b[];
a[] = b[] + c[];
a[] = f(b[]);
would mean
foreach(ref e;a) e = n;
foreach(i,ref e;a) e = b[i];
foreach(i,ref e;a) e = b[i] + c[i];
foreach(i,ref e;a) e = f(b[i]);
respectively. But if so, the plan got dropped a long time ago, and now
only the first two cases work.
(Disclaimer: I may have got that completely wrong).
I don't see the problem with the foreach version though. It's
certainly transparent.
This raises an interesting point. So the typesaftly issue could be
solved like:
foo(array[]);
-Joel
Did you mean dot(val1, val2); here?
IMO, it saves you a little of typing, but you loose control over code =
execution.
It is hard to debug, it adds additional ambiguity.
f(char[] s);
f(char c);
char[] chars;
f(chars); // f(char[] s) is called, but I need foreach(), what should I =
do?
It is easy to write a template, that would do what you want:
template ReturnType(CallableType, TList...)
{
CallableType c;
TList u;
static if (is(typeof(c(u)) =3D=3D void)) {
alias void Value;
} else {
alias typeof(c(u))[] Value;
}
}
template auto_foreach(CallableType, ElementType)
{
ReturnType!(CallableType,ElementType).Value auto_foreach(CallableTy=
pe =
callable, ElementType[] elements)
{
alias ReturnType!(CallableType,ElementType).Value Type;
static if (is(Type =3D=3D void)) {
foreach(e; elements) {
callable(e);
}
} else {
Type result;
result.length =3D elements.length;
int i =3D 0;
foreach (e; elements) {
result[i++] =3D callable(e);
}
return result;
}
}
}
void putc(char c)
{
printf("%c", c);
}
char shift(char c)
{
return c+1;
}
int main(string[] args)
{
char[] h =3D "hello";
h =3D auto_foreach(&shift, h);
auto_foreach(&putc, h);
return 0;
}
You could also change this template to accept multiple arrays as input. =
=
It's easy (use variadic template + recursion).
Make more practice in generic programming, it is worth it!
Apr 27 2008
↑↓←→ Bill Baxter <dnewsgroup billbaxter.com> writes:
janderson wrote:
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?
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think I prefer:
foo(array[]);
-Joel
That could work with member functions too:
array[].foo();
-Joel
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think I prefer:
foo(array[]);
-Joel
That could work with member functions too:
array[].foo();
-Joel
And slices:
array[0..5].foo();
-Joel
Apr 27 2008
↑ ↓ ←→ Bill Baxter <dnewsgroup billbaxter.com> writes:
janderson wrote:
Bill Baxter wrote:
janderson wrote:
What do you think?
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think I prefer:
foo(array[]);
I think that already means call foo with a full slice of array, doesn't
it? Anyway, even if it doesn't you can overload opSlice() currently so
that array[] can mean anything you want it to.
--bb
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think I prefer:
foo(array[]);
I think that already means call foo with a full slice of array, doesn't
it? Anyway, even if it doesn't you can overload opSlice() currently so
that array[] can mean anything you want it to.
--bb
That's the point though. If there's already an overload available then
that should be used. It allows you to come along later and write
specialized behavior.
-Joel
Apr 27 2008
↑ ↓ ←→ Bill Baxter <dnewsgroup billbaxter.com> writes:
janderson wrote:
Bill Baxter wrote:
janderson wrote:
Bill Baxter wrote:
janderson wrote:
What do you think?
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think I prefer:
foo(array[]);
I think that already means call foo with a full slice of array,
doesn't it? Anyway, even if it doesn't you can overload opSlice()
currently so that array[] can mean anything you want it to.
--bb
That's the point though. If there's already an overload available then
that should be used. It allows you to come along later and write
specialized behavior.
Ok I suppose. As long as you're aware what your proposing will break
existing code, which means the barrier for accepting the proposal will
be a lot higher.
--bb
I think it's already hard enough to figure out what's going to get
called by something like foo(array)
It could be
- foo(int[] x)
- foo(int[] x...)
- foo(T)(T x)
- foo(T)(T[] x)
- foo(T...)(T x)
- struct foo { static foo opCall(int[]); }
- struct foo { static foo opCall(int[]...); }
- struct foo { static foo opCall(T)(T x); } etc
- or struct Foo with non-static opCall on instance foo
- or all the same stuff on class ...
So I don't think another meaning for foo(array) is really helpful.
I *do* like the idea of an expression (not a statement) that has
foreach-like abilities. But I think it should come with some
distinguishing syntax.
In Python it's just [expr(x) for x in array]
Which resonates with Pythons normal loopoing:
for x in array: expr(x)
So direct translation of that idea to D would be
[expr(x) foreach(x; array)];
Seems not so terrible a syntax to me.
--bb
I think I prefer:
foo(array[]);
I think that already means call foo with a full slice of array,
doesn't it? Anyway, even if it doesn't you can overload opSlice()
currently so that array[] can mean anything you want it to.
--bb
That's the point though. If there's already an overload available
then that should be used. It allows you to come along later and write
specialized behavior.
Ok I suppose. As long as you're aware what your proposing will break
existing code, which means the barrier for accepting the proposal will
be a lot higher.
--bb
Actually, I should have said that, in general, Joel's proposal is
undefined for all non-unary operations.
a[] = b[] + c[]
f(a[], b[], c[], d[])
etc.
My proposal was to generate nested loops and base it of the order the
arrays where specified. However it could just as easily be parallel for
all values and require that all arrays are the same size.
-Joel
I think I'd be happy with a template in std.algorithm.
// a[] = b[] + c[]
auto a = parallel!("a = b + c")(a,b,c);
// foo(array1[], array2[], array3[], array4[])
parallel!("foo(a,b,c,d)")(array1,array2,array3,array4);
Or some such. I'm sure Andrei could write that. He's a clever guy.
Basically, that would be an equivalent of the "map" function present in
functional programming languages.
Actually, I should have said that, in general, Joel's proposal is
undefined for all non-unary operations.
a[] = b[] + c[]
f(a[], b[], c[], d[])
arrays where specified. However it could just as easily be parallel for all
values and require that all arrays are the same size.
I think I'd be happy with a template in std.algorithm.
// a[] = b[] + c[]
auto a = parallel!("a = b + c")(a,b,c);
// foo(array1[], array2[], array3[], array4[])
parallel!("foo(a,b,c,d)")(array1,array2,array3,array4);
Or some such. I'm sure Andrei could write that. He's a clever guy.
I don't know. Might as well use a foreach if its going to start looking
like that.
-Joel
The problem is that [] already has a defined meaning.
struct S
{
R opSlice() { ... }
}
S array;
foo(array[]);
should call
foo(array.opSlice());
so then you'd have to do
foo(array[][]);
to disambiguate.
Personally, I see absolutely no use for the /existing/ use of [],
whereby array[] means array[0..$]. I won't feel a moment's pang of
regret if this usage were dropped. That would free up [] to be
redeployed for "vector operations".
Your suggestion would still ambiguous even if [] were redeployed.
Bill's wouldn't. Consider
f(a[]) + g(b[])
Do we mean
f([x foreach(x:a)]) + g([y foreach(y:b)])
or
[f(x) + g(b[i]) foreach(i,x:a)]
?
I have to say, I prefer a variation of Bill's syntax. I'd want foreach
at the front, not at the back. Python tries to be more like natural
language, but D wants to be more compiler-friendly (easy to parse). So
I'd want
[foreach(x:a) expr(x)]
Actually, I should have said that, in general, Joel's proposal is
undefined for all non-unary operations.
a[] = b[] + c[]
f(a[], b[], c[], d[])
arrays where specified. However it could just as easily be parallel for all
values and require that all arrays are the same size.
I think I'd be happy with a template in std.algorithm.
// a[] = b[] + c[]
auto a = parallel!("a = b + c")(a,b,c);
// foo(array1[], array2[], array3[], array4[])
parallel!("foo(a,b,c,d)")(array1,array2,array3,array4);
Or some such. I'm sure Andrei could write that. He's a clever guy.
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.
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.
you get 1 functions call and N loop-body executions
but if you let d loop the function you get N function calls and N body
excutions.
You are adding N-1 extra function calls !
Knud
Apr 27 2008
↑↓← → Edward Diener <eddielee_no_spam_here tropicsoft.com> writes:
janderson wrote:
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);
}
I think people have missed the point on my suggestion. I wanted
something that I could use within a template (see example at bottom).
Something that I could override later or use the overridden case (if
someone had already written a function to handle arrays of that type).
I often write functions like:
int Covert(int a)
{
...
}
Then endup writing an array version as well.
int[] Convert(int[] a)
{
int result[];
result.length = a.length;
int i=0;
foreach( ; )
{
result [i++];
}
}
80% of the time the array version is pretty much the same thing. So a
while back I wrote a template that works like:
void foo(int i)
{
printf("B");
}
alias AutoForeach!(foo, int) foo;
Then I could go:
for(6); //Prints "B"
int[] array;
array = 2;
foo(array); //Prints "BB"
But then I couldn't specialize it later without removing the alias,
because I'd get a name clash.
The other problem is this won't do cases like:
result ~= foo(array);
or
foo(foo1(array)); //Runs foo and foo1 array.length times.
It started cutting my code size down by about 30%. So I thought it
might be a good idea for the language. The language would be able to
provide provide the candy that you would never be able to get with
templates.
//////////////////////////////////////////////////
//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.
So it's equivalent to:
foreach (auto val; array1)
{
write(val);
}
foreach (auto val; array2)
{
write(val);
}
write(value);
Apr 28 2008
↑ ↓ ←→ Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
janderson wrote:
while back I wrote a template that works like:
void foo(int i)
{
printf("B");
}
alias AutoForeach!(foo, int) foo;
Then I could go:
for(6); //Prints "B"
int[] array;
array = 2;
foo(array); //Prints "BB"
But then I couldn't specialize it later without removing the alias,
because I'd get a name clash.
The other problem is this won't do cases like:
result ~= foo(array);
Why not? Didn't you define AutoForeach!(foo, int) to return an int[] ?
or
foo(foo1(array)); //Runs foo and foo1 array.length times.
while back I wrote a template that works like:
void foo(int i)
{
printf("B");
}
alias AutoForeach!(foo, int) foo;
Then I could go:
for(6); //Prints "B"
int[] array;
array = 2;
foo(array); //Prints "BB"
But then I couldn't specialize it later without removing the alias,
because I'd get a name clash.
The other problem is this won't do cases like:
result ~= foo(array);
Why not? Didn't you define AutoForeach!(foo, int) to return an int[] ?
Your right a AutoForEachReturn could work here.
or
foo(foo1(array)); //Runs foo and foo1 array.length times.
I forgot to mention that in that example foo1 was defined with the
autoforeach, foo was not (and it wouldn't work even if I did).
Then we could all make our own little specific loops, which is far more
reasonable. Your idea is well demonstrated, but I don't like the syntax.
It doesn't really tell you what is going on just by looking at it.
PS: You also might want to look at 'map' in phobos2's std.algorithm.
Apr 28 2008
↑ ↓ ←→ Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrod wrote:
What do you think?
Then we could all make our own little specific loops, which is far more
reasonable. Your idea is well demonstrated, but I don't like the syntax.
It doesn't really tell you what is going on just by looking at it.
PS: You also might want to look at 'map' in phobos2's std.algorithm.
Python has map() too, but people prefer to use list comprehensions for
some reason.
--bb
Apr 28 2008
↑ ↓ ←→ Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Bill Baxter wrote:
Jarrod wrote:
What do you think?
Then we could all make our own little specific loops, which is far
more reasonable. Your idea is well demonstrated, but I don't like the
syntax. It doesn't really tell you what is going on just by looking at
it.
PS: You also might want to look at 'map' in phobos2's std.algorithm.
Python has map() too, but people prefer to use list comprehensions for
some reason.
--bb
Comprehensions might be syntactically nicer than map, but as for the
original proposal (automatic foreach), the map construct covers it quite
nicely and sufficiently.
--
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Apr 29 2008
↑ ↓ ←→ Brian Myers <bmyers harryanddavid.com> writes:
I'm getting the following error messages now. Does SwapStrategy have to be
specified at compile time?
C:\Documents and Settings\dag033\D\d_dedup>dmd -g d_dedup.d
..\d_libcsv\d_libcsv.d ..\d_libcsv\csv.d ..\d_libcsv\bin\deb
ug\d_libcsv.lib
c:\dmd\bin\..\src\phobos\std\algorithm.d(2632): Error: expression ss ==
cast(SwapStrategy)0 is not constant or does not
evaluate to a bool
c:\dmd\bin\..\src\phobos\std\algorithm.d(2655): static assert (ss !=
cast(SwapStrategy)1) is not evaluatable at compile
time
Here's the call to schwartzSort!:
protected:
SwapStrategy ss;
.
.
.
schwartzSort!(kx.get_key, "a < b", ss)(lines);
Thanx
Brian
Apr 29 2008
↑ ↓ ← → Brian Myers <bmyers harryanddavid.com> writes:
Argh, sorry, meant this to be a new topic post. I'll try again.
Brian Myers Wrote:
I'm getting the following error messages now. Does SwapStrategy have to be
specified at compile time?
C:\Documents and Settings\dag033\D\d_dedup>dmd -g d_dedup.d
..\d_libcsv\d_libcsv.d ..\d_libcsv\csv.d ..\d_libcsv\bin\deb
ug\d_libcsv.lib
c:\dmd\bin\..\src\phobos\std\algorithm.d(2632): Error: expression ss ==
cast(SwapStrategy)0 is not constant or does not
evaluate to a bool
c:\dmd\bin\..\src\phobos\std\algorithm.d(2655): static assert (ss !=
cast(SwapStrategy)1) is not evaluatable at compile
time
Here's the call to schwartzSort!:
protected:
SwapStrategy ss;
.
.
.
schwartzSort!(kx.get_key, "a < b", ss)(lines);
Thanx
Brian