digitalmars.D - Automatic Foreach
- janderson (166/166) Apr 26 2008 I know Walter has his head stuck in Const/Invarient/Pure multithreading
- Janice Caron (16/16) Apr 27 2008 Something at the back of my mind tells me that, once upon a time,
- Bill Baxter (4/27) Apr 27 2008 Maybe its the compiler error message that says "vector operations are
- janderson (5/27) Apr 27 2008 This raises an interesting point. So the typesaftly issue could be
- Koroskin Denis (62/78) Apr 27 2008 Did you mean dot(val1, val2); here?
- Bill Baxter (25/255) Apr 27 2008 I think it's already hard enough to figure out what's going to get
- janderson (4/38) Apr 27 2008 I think I prefer:
- janderson (4/45) Apr 27 2008 That could work with member functions too:
- janderson (4/53) Apr 27 2008 And slices:
- Bill Baxter (5/44) Apr 27 2008 I think that already means call foo with a full slice of array, doesn't
- janderson (5/51) Apr 27 2008 That's the point though. If there's already an overload available then
- Bill Baxter (5/56) Apr 27 2008 Ok I suppose. As long as you're aware what your proposing will break
- janderson (2/60) Apr 27 2008 How?
- Janice Caron (2/6) Apr 27 2008 auto a = array1[] ~ array2[];
- Janice Caron (5/5) Apr 27 2008 Actually, I should have said that, in general, Joel's proposal is
- janderson (5/13) Apr 27 2008 My proposal was to generate nested loops and base it of the order the
- Janice Caron (7/18) Apr 27 2008 I think I'd be happy with a template in std.algorithm.
- Janice Caron (17/19) Apr 27 2008 The problem is that [] already has a defined meaning.
- Janice Caron (14/16) Apr 27 2008 Your suggestion would still ambiguous even if [] were redeployed.
- Knud Soerensen (11/28) Apr 27 2008 Have a look at the vectorization suggestion
- Edward Diener (5/39) Apr 27 2008 foreach(auto value; array)
- BCS (16/19) Apr 27 2008 how about
- janderson (63/63) Apr 28 2008 I think people have missed the point on my suggestion. I wanted
- Bruno Medeiros (6/34) Apr 29 2008 Same as above.
- janderson (4/39) Apr 29 2008 I forgot to mention that in that example foo1 was defined with the
- terranium (7/23) Apr 28 2008 This is better but still is too inobvious.
- terranium (2/5) Apr 28 2008 ps and I don't think an automatic resize to be a good idea.
- terranium (2/5) Apr 28 2008 This is a problem :/
- terranium (2/5) Apr 28 2008 array.foo() also has an existing meaning of foo(array)
- Jarrod (5/6) Apr 28 2008 I think Walter really needs to get macros implemented in D.
- Bill Baxter (4/13) Apr 28 2008 Python has map() too, but people prefer to use list comprehensions for
- Bruno Medeiros (7/23) Apr 29 2008 Comprehensions might be syntactically nicer than map, but as for the
- Brian Myers (16/16) Apr 29 2008 I'm getting the following error messages now. Does SwapStrategy have to ...
- Brian Myers (2/24) Apr 29 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?
Apr 26 2008
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
Janice Caron wrote:Something at the back of my mind tells meMaybe 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.
Apr 27 2008
Janice Caron wrote: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
Apr 27 2008
On Sun, 27 Apr 2008 10:45:36 +0400, janderson <askme me.com> wrote:////////////////////////////////////////////////// //Example 3 ////////////////////////////////////////////////// // Multiple array inputs should work like nested arrays. vector[] vertex =3D dot(array1, array2); Equivalent too: vector[] vertex; vector.length =3D array1.length * array2.length; int i=3D0; foreach (auto val1; array1) { foreach (auto val2; array2) { vertex[i++] =3D sqrt(val1, val2); } }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
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
Apr 27 2008
Bill Baxter wrote:janderson wrote:I think I prefer: foo(array[]); -JoelWhat 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
Apr 27 2008
janderson wrote:Bill Baxter wrote:That could work with member functions too: array[].foo(); -Joeljanderson wrote:I think I prefer: foo(array[]); -JoelWhat 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
Apr 27 2008
janderson wrote:janderson wrote:And slices: array[0..5].foo(); -JoelBill Baxter wrote:That could work with member functions too: array[].foo(); -Joeljanderson wrote:I think I prefer: foo(array[]); -JoelWhat 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
Apr 27 2008
janderson wrote:Bill Baxter wrote: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. --bbjanderson wrote:I think I prefer: foo(array[]);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
Apr 27 2008
Bill Baxter wrote:janderson wrote: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. -JoelBill Baxter wrote: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. --bbjanderson wrote:I think I prefer: foo(array[]);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
Apr 27 2008
janderson wrote:Bill Baxter wrote: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. --bbjanderson wrote: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.Bill Baxter wrote: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. --bbjanderson wrote:I think I prefer: foo(array[]);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
Apr 27 2008
Bill Baxter wrote:janderson wrote:How?Bill Baxter wrote: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. --bbjanderson wrote: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.Bill Baxter wrote: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. --bbjanderson wrote:I think I prefer: foo(array[]);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
Apr 27 2008
On 27/04/2008, janderson <askme me.com> wrote:auto a = array1[] ~ array2[];Ok I suppose. As long as you're aware what your proposing will breakexisting code, which means the barrier for accepting the proposal will be a lot higher. How?
Apr 27 2008
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.
Apr 27 2008
Janice Caron wrote: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
Apr 27 2008
On 27/04/2008, janderson <askme me.com> wrote:Janice Caron wrote: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.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[])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.
Apr 27 2008
Janice Caron a écrit :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.
Apr 27 2008
Janice Caron wrote:On 27/04/2008, janderson <askme me.com> wrote:I don't know. Might as well use a foreach if its going to start looking like that. -JoelJanice Caron wrote: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.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[])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.
Apr 27 2008
On 27/04/2008, janderson <askme me.com> wrote:I think I prefer: foo(array[]);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".
Apr 27 2008
On 27/04/2008, janderson <askme me.com> wrote:I think I prefer: foo(array[]);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)]
Apr 27 2008
Have a look at the vectorization suggestion http://all-technology.com/eigenpolls/dwishlist/index.php?it=10 on the wish list. http://all-technology.com/eigenpolls/dwishlist/ 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.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.if you encapsulating the loop in the function 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
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); }foreach(auto value; array) { foo(value); }becomes: foo(array);
Apr 27 2008
Reply to janderson,float[] array; array ~= sqrt(array2);how about char[] to; char[][] from; to ~= from; goes to uint add=0; foreach(a;from) add+=a.length; to.length += add; foreach(a;from) { to[$-add,$-add+a.length = a[] add-= a.length; } ??
Apr 27 2008
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
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.Same as above. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Apr 29 2008
Bruno Medeiros wrote:janderson wrote:Your right a AutoForEachReturn could work here.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[] ?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).or foo(foo1(array)); //Runs foo and foo1 array.length times.Same as above.
Apr 29 2008
This is better but still is too inobvious. How about making it a variant of foreach? foreach a[] = n; foreach a[] = b[]; foreach a[] = b[] + c[]; foreach a[] = f(b[]); foreach { a[] = f(b[]); d[]=b[]+c[]; }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]);This raises an interesting point. So the typesaftly issue could be solved like: foo(array[]);
Apr 28 2008
janderson Wrote:This raises an interesting point. -Joelps and I don't think an automatic resize to be a good idea.
Apr 28 2008
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.This is a problem :/ For what reason the entire slice exists for in fact? Does it have any meaning?
Apr 28 2008
Bill Baxter Wrote: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.array.foo() also has an existing meaning of foo(array)
Apr 28 2008
What do you think?I think Walter really needs to get macros implemented in D. 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
Jarrod wrote:Python has map() too, but people prefer to use list comprehensions for some reason. --bbWhat do you think?I think Walter really needs to get macros implemented in D. 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 wrote:Jarrod wrote: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#DPython has map() too, but people prefer to use list comprehensions for some reason. --bbWhat do you think?I think Walter really needs to get macros implemented in D. 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 29 2008
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
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
Apr 29 2008