D - Ideas for D
- Tintor Marko (168/169) Oct 27 2003 0) templates
- davepermen (22/22) Oct 28 2003 the template thing is something i'm eagerly waiting for. i have very muc...
- Tintor Marko (4/177) Oct 30 2003 --
- Andy Friesen (72/261) Oct 30 2003 An important part of D is that it be easy to implement. (or much easier
- Antti =?iso-8859-1?Q?Syk=E4ri?= (117/127) Oct 30 2003 I think named and optional function parameters could be added should be
- Felix (8/194) Oct 31 2003 Yes, I like most of them... especially the array stuff. I also would lik...
- Sean L. Palmer (28/228) Oct 31 2003 Yes, if D had ranges, and good multidimensional array handling and array
- Matthew Wilson (5/12) Oct 31 2003 I'm more in the former camp as a rule, but with templates it's more than
- Sean L. Palmer (5/18) Oct 31 2003 You mean without implicit instantiation?
- Ilya Minkov (28/29) Oct 31 2003 Most of the STL and almost any other C++ template library out there
- Matthew Wilson (4/23) Oct 31 2003 the
- Walter (4/5) Nov 01 2003 Lots of great ideas there. Some are already in the queue to be implement...
- Matthias Becker (7/15) Oct 31 2003 But it doesn't fit into the language very well, does it?
- Tintor Marko (3/20) Oct 31 2003 Why it doesn't fit?
0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisation 1) foreach foreach(A a, B b; m) ... // multiple iterator foreach, this calls first apply foreach(A a; m) ... // second apply class M // and multiple apply functions { int apply(int delegate(A,B) dg) {...} int apply(int delegate(A) dg) {...} } for associative arrays: string[string] index ... foreach(string key, string value; index) ... (that is the use of int returned from apply?) another form: foreach(a in m) ... // easyer to read foreach(char c, int i; str) // c is every char from str, i is index of c in str int[][] a; foreach(int a; matrix) // for each element of matrix foreach(char a; "string") // for each character of string // iterating with custom functions or delegates int func(int x, delegate(int) dg) {...} foreach(int a in func(2)) ... 2) function parameters int f(int a=2, int b) {..} // default values int g(int a, int b=2) {..} ... g(1); // called g(1,2); Optional parameter names in calls: f(b:6); // this is called as f(2,6); // grouping of values in function definition int f(out int a, b, c) // same as intf(out int a, out int b, out int c) int m(int a, b, long c, d) {..} // same as int m(int a, int b, long c, long d) 3) switch case with range and multiple values: switch(x) { ... case a..b: ... // if a <= x <= b (or perhaps a <= x < b) case 1,3,5,7..9: ... ... } break is not neaded at the end of case, but can be used to early exit exception should not be thrown if case for some value is not found and there is no 'default' universal switch: any basic type, arrays (not just strings), struct, enum, class with eq() can be used in switch 4) power operator (^) for integer, real and complex numbers (~) can be used for inverting and xoring like (-) 5) word logical operators: and (&&), or (||), not(!) (it is easyer to read) not in operator: if('a' not in "ABa") instead of if(!('a' in "ABa")) 6) connected comparison operations 2 <= x < y <= 9 instead of (2 <= x) and (x < y) and (y <= 9) 7) set type (implemented as static array of bits on stack) set NAME {SYMBOL [, SYMBOL..]} [= SYMBOL [| SYMBOL..]]; // initializer for type, default is 0 (empty set) set Set {...}; Set A,B; operations: Set[i] // i+1-th symbol from set type Set[i].toString Set.max A == B // simple comparison A.count, A.max // number of elements and maximum number of elements e in A // is e element of A A in B // are all elements from A in B ~A // complement of A A | B // set union A & B // set intersection A / B // elements in A, but not in B A = 0 or A = {} // clears A A = e|d|f or A = {e,f,d} // init set with elements e, d and f &=, |=, /= oprators 8) multiple expression assert assert x>0, y>0, z>0; instead of assert(x>0); assert(y>0); assert(z>0); assert error should print entire expression that failed, line number and source file 9) arrays can be created at runtime int a[] = [1,2,4..7]; // 1,2,4,5,6,7 int b = 5; a ~= [4,b]; bar([6,9,b,b+2,5..9]); 10) compile time overlaping copies: a[0..3] = a[1..4]; a[0..3] = a[1..]; // 4 is not neaded a[0..] = a[1..4]; // 3 is not neaded 11) aliases string, wstring and dstring for char[], wchar[] and dchar[] 12) variable parrameter lists, array is created from last parrameters real average(real[...] n) {real r; for(real i in n) r+=i; return r/n.length;} // or real average(real[] n...) average(1,2,3,4,5); average([1,2,3,4,5]); // same as above 13) some type that can contain every other type (var for example) var x = 9; x = "abc"; x = new File; x = null; // type of x is now void* some mechanism for getting type of var: if(x.typeinfo == int.typeinfo) ... or more simpler: if(x is int) ... // if x is of type int Object obj = new File; if(obj is File) ... 14) with 12 and 13 from above safer, easyer and expandable printf can be created void printf(string format, var[...] args) type info is in var[] and can be eliminated from format string: printf("int = %, real = %, string = %, object = %\n", 5, 0.2, "ba", obj); for objects of type class and struct member function toString() is called for printing 15) min, max and swap functions with variable parameter count for all types swap(a,b,c) {x=a; a=b; b=c; c=x;} 16) class objects on stack (vtable is not needed is this case): stack File file("..."); // create file on stack 17) with keyword for struct types 18) exceptions thrown on segmentation violation error, with file and line where it occured 19) integer / and % are wrong: (-1) % 5 is 4, it is not -(1 % 5) = -1 (a%b= 0, a%b < b)real divide 1.0/0.0 should be NAN, not +INF (same for -1.0/0.0) 20) overloadable functions with diferent return types: void func() {} real func() {} uint func() {} func(); // calls first func (real)func(); // calls second func real v = (real)(uint)func(); // calls third func, and converts result to real 21) constructors and destructors for structs 22) no commutative vesions of + and * for operator overloading 23) enum Color {red, blue} Color a = red; // not Color a = Color.red; 24) multiple dimension dynamic arrays int[,] a = new int[3,5]; // 3x5 dynamic matrix a[2,2] = 3; // set one element a[1] // returns array of 5 elements from second row a.dim[0] // returns 3 a.dim[1] // returns 5 a.length // returns 3*5 a.resize(5,10) // reallocate storage for matrix, preserving old elements 25) overloadable ++ and -- operators 26) every object should have overloadable dup property 27) for identifiers same as keywords class class {int int;} // class named "class" with int named "int" 28) some way to extract mantisa and exponent from floating point numbers (properties?) 29) fixed precision real type 32 and 64 bits 30) exception should be thrown if mathematical error occurs class EIntZeroDivide: Exception {...} class EDomain: Exception {...} class EZeroDivide: EDomain {...} 31) properties for arrays: min, max, last, push, pop BUGS: 1) foreach doesn't work with inout struct as iterator 2) aliases of struct in template doesn't work when used as types 3) ++ and -- operator doesn't work for properties: char[] a = new char[10]; a.length++; // compile error 4) this works, but it is an error (input-only reference is returned) Object dd(Object a) {return a;} MISC: What about interpretator and using D for scripting?
Oct 27 2003
the template thing is something i'm eagerly waiting for. i have very much need for such a way to use them. constructors and destructors for structs would be sort of nice, too and if not constructors and destructors, then at least same-named overloaded functions.. like this: struct vec3 { float x,y,z; } vec3 vec3(float x,float y,float z) { vec3 ret; ret.x = x; ret.y = y; ret.z = z; return ret; } but of course, a this() would be best. destructors? not sure. as structs are simple data-types, they should NOT need destructors, as they should NOT need to shut down from some sort of "state". but constructors help to faster init the structs.. wich would be nice. and the templates are really needed... remove explicit type instantiations. THE feature of templates in c++ is that it detects on itself what types it has to use.
Oct 28 2003
any comments? On Mon, 27 Oct 2003 21:10:19 +0100, Tintor Marko <elud verat.net> wrote:0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisation 1) foreach foreach(A a, B b; m) ... // multiple iterator foreach, this calls first apply foreach(A a; m) ... // second apply class M // and multiple apply functions { int apply(int delegate(A,B) dg) {...} int apply(int delegate(A) dg) {...} } for associative arrays: string[string] index ... foreach(string key, string value; index) ... (that is the use of int returned from apply?) another form: foreach(a in m) ... // easyer to read foreach(char c, int i; str) // c is every char from str, i is index of c in str int[][] a; foreach(int a; matrix) // for each element of matrix foreach(char a; "string") // for each character of string // iterating with custom functions or delegates int func(int x, delegate(int) dg) {...} foreach(int a in func(2)) ... 2) function parameters int f(int a=2, int b) {..} // default values int g(int a, int b=2) {..} ... g(1); // called g(1,2); Optional parameter names in calls: f(b:6); // this is called as f(2,6); // grouping of values in function definition int f(out int a, b, c) // same as intf(out int a, out int b, out int c) int m(int a, b, long c, d) {..} // same as int m(int a, int b, long c, long d) 3) switch case with range and multiple values: switch(x) { ... case a..b: ... // if a <= x <= b (or perhaps a <= x < b) case 1,3,5,7..9: ... ... } break is not neaded at the end of case, but can be used to early exit exception should not be thrown if case for some value is not found and there is no 'default' universal switch: any basic type, arrays (not just strings), struct, enum, class with eq() can be used in switch 4) power operator (^) for integer, real and complex numbers (~) can be used for inverting and xoring like (-) 5) word logical operators: and (&&), or (||), not(!) (it is easyer to read) not in operator: if('a' not in "ABa") instead of if(!('a' in "ABa")) 6) connected comparison operations 2 <= x < y <= 9 instead of (2 <= x) and (x < y) and (y <= 9) 7) set type (implemented as static array of bits on stack) set NAME {SYMBOL [, SYMBOL..]} [= SYMBOL [| SYMBOL..]]; // initializer for type, default is 0 (empty set) set Set {...}; Set A,B; operations: Set[i] // i+1-th symbol from set type Set[i].toString Set.max A == B // simple comparison A.count, A.max // number of elements and maximum number of elements e in A // is e element of A A in B // are all elements from A in B ~A // complement of A A | B // set union A & B // set intersection A / B // elements in A, but not in B A = 0 or A = {} // clears A A = e|d|f or A = {e,f,d} // init set with elements e, d and f &=, |=, /= oprators 8) multiple expression assert assert x>0, y>0, z>0; instead of assert(x>0); assert(y>0); assert(z>0); assert error should print entire expression that failed, line number and source file 9) arrays can be created at runtime int a[] = [1,2,4..7]; // 1,2,4,5,6,7 int b = 5; a ~= [4,b]; bar([6,9,b,b+2,5..9]); 10) compile time overlaping copies: a[0..3] = a[1..4]; a[0..3] = a[1..]; // 4 is not neaded a[0..] = a[1..4]; // 3 is not neaded 11) aliases string, wstring and dstring for char[], wchar[] and dchar[] 12) variable parrameter lists, array is created from last parrameters real average(real[...] n) {real r; for(real i in n) r+=i; return r/n.length;} // or real average(real[] n...) average(1,2,3,4,5); average([1,2,3,4,5]); // same as above 13) some type that can contain every other type (var for example) var x = 9; x = "abc"; x = new File; x = null; // type of x is now void* some mechanism for getting type of var: if(x.typeinfo == int.typeinfo) ... or more simpler: if(x is int) ... // if x is of type int Object obj = new File; if(obj is File) ... 14) with 12 and 13 from above safer, easyer and expandable printf can be created void printf(string format, var[...] args) type info is in var[] and can be eliminated from format string: printf("int = %, real = %, string = %, object = %\n", 5, 0.2, "ba", obj) ; for objects of type class and struct member function toString() is called for printing 15) min, max and swap functions with variable parameter count for all types swap(a,b,c) {x=a; a=b; b=c; c=x;} 16) class objects on stack (vtable is not needed is this case): stack File file("..."); // create file on stack 17) with keyword for struct types 18) exceptions thrown on segmentation violation error, with file and line where it occured 19) integer / and % are wrong: (-1) % 5 is 4, it is not -(1 % 5) = -1 (a%b-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/= 0, a%b < b)real divide 1.0/0.0 should be NAN, not +INF (same for -1.0/0.0) 20) overloadable functions with diferent return types: void func() {} real func() {} uint func() {} func(); // calls first func (real)func(); // calls second func real v = (real)(uint)func(); // calls third func, and converts result to real 21) constructors and destructors for structs 22) no commutative vesions of + and * for operator overloading 23) enum Color {red, blue} Color a = red; // not Color a = Color.red; 24) multiple dimension dynamic arrays int[,] a = new int[3,5]; // 3x5 dynamic matrix a[2,2] = 3; // set one element a[1] // returns array of 5 elements from second row a.dim[0] // returns 3 a.dim[1] // returns 5 a.length // returns 3*5 a.resize(5,10) // reallocate storage for matrix, preserving old elements 25) overloadable ++ and -- operators 26) every object should have overloadable dup property 27) for identifiers same as keywords class class {int int;} // class named "class" with int named "int" 28) some way to extract mantisa and exponent from floating point numbers (properties?) 29) fixed precision real type 32 and 64 bits 30) exception should be thrown if mathematical error occurs class EIntZeroDivide: Exception {...} class EDomain: Exception {...} class EZeroDivide: EDomain {...} 31) properties for arrays: min, max, last, push, pop BUGS: 1) foreach doesn't work with inout struct as iterator 2) aliases of struct in template doesn't work when used as types 3) ++ and -- operator doesn't work for properties: char[] a = new char[10]; a.length++; // compile error 4) this works, but it is an error (input-only reference is returned) Object dd(Object a) {return a;} MISC: What about interpretator and using D for scripting?
Oct 30 2003
Tintor Marko wrote:any comments?You asked for it. >:)On Mon, 27 Oct 2003 21:10:19 +0100, Tintor Marko <elud verat.net> wrote:An important part of D is that it be easy to implement. (or much easier to implement than C++, at any rate) I agree that something like this would be a godsend, but whether there is a simpler way to get the functionality remains to be seen.0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisationAlso nice, but not hugely so, I don't think.1) foreach foreach(A a, B b; m) ... // multiple iterator foreach, this calls first apply foreach(A a; m) ... // second apply class M // and multiple apply functions { int apply(int delegate(A,B) dg) {...} int apply(int delegate(A) dg) {...} } for associative arrays: string[string] index ... foreach(string key, string value; index) ... (that is the use of int returned from apply?) another form: foreach(a in m) ... // easyer to read foreach(char c, int i; str) // c is every char from str, i is index of c in str int[][] a; foreach(int a; matrix) // for each element of matrix foreach(char a; "string") // for each character of string // iterating with custom functions or delegates int func(int x, delegate(int) dg) {...} foreach(int a in func(2)) ... 2) function parameters int f(int a=2, int b) {..} // default values int g(int a, int b=2) {..}... unless named arguments were thrown in, a la Python. There's plenty of room for gushy syntactical things where named arguments are concerned. Not very realistic in a statically typed langauge, though.... g(1); // called g(1,2); Optional parameter names in calls: f(b:6); // this is called as f(2,6);meh. Saves a tiny bit of typing, but it doesn't help express anything.// grouping of values in function definition int f(out int a, b, c) // same as intf(out int a, out int b, out int c) int m(int a, b, long c, d) {..} // same as int m(int a, int b, long c, long d)I don't see why not, but I don't really use switch/case much. I usually make sure there's no better way to do something before resorting to a switch/case. (polymorphism is cool) Switch case /does/ find use when there's an extremely limited domain. (four or five possibilities) That's about it.3) switch case with range and multiple values: switch(x) { ... case a..b: ... // if a <= x <= b (or perhaps a <= x < b) case 1,3,5,7..9: ... ... }Been argued many times over the ages. We'll just say that there are enough people who like the present behaviour that it should stay.break is not neaded at the end of case, but can be used to early exitI disagree. That's a subtlety that I had never even considered before D. I think it's a good call.exception should not be thrown if case for some value is not found and there is no 'default'See above. :)universal switch: any basic type, arrays (not just strings), struct, enum, class with eq() can be used in switchNo way. Just no. Exponents aren't so common as to desperately need their own operator anyway.4) power operator (^) for integer, real and complex numbers (~) can be used for inverting and xoring like (-)Would be nice, but not earth shattering.5) word logical operators: and (&&), or (||), not(!) (it is easyer to read) not in operator: if('a' not in "ABa") instead of if(!('a' in "ABa"))Also nice. Also not earth shattering.6) connected comparison operations 2 <= x < y <= 9 instead of (2 <= x) and (x < y) and (y <= 9)A bit heavier than is realistic as a language primitive. You'd be better implementing this within D, and not as a part of D.7) set type (implemented as static array of bits on stack) set NAME {SYMBOL [, SYMBOL..]} [= SYMBOL [| SYMBOL..]]; // initializer for type, default is 0 (empty set) set Set {...}; Set A,B; operations: Set[i] // i+1-th symbol from set type Set[i].toString Set.max A == B // simple comparison A.count, A.max // number of elements and maximum number of elements e in A // is e element of A A in B // are all elements from A in B ~A // complement of A A | B // set union A & B // set intersection A / B // elements in A, but not in B A = 0 or A = {} // clears A A = e|d|f or A = {e,f,d} // init set with elements e, d and f &=, |=, /= opratorsJust use && :)8) multiple expression assert assert x>0, y>0, z>0; instead of assert(x>0); assert(y>0); assert(z>0); assert error should print entire expression that failed, line number and source fileVery handy.9) arrays can be created at runtime int a[] = [1,2,4..7]; // 1,2,4,5,6,7 int b = 5; a ~= [4,b]; bar([6,9,b,b+2,5..9]);No opinion. Would be nice occasionally, but not really frequently. I would be perfectly happy if the array type grew some extra methods, for things like insertion and deletion. (from arbitrary indeces)10) compile time overlaping copies: a[0..3] = a[1..4]; a[0..3] = a[1..]; // 4 is not neaded a[0..] = a[1..4]; // 3 is not neadedNothing stopping you from doing this in your own code, except for causing conflicts with the standard string module.11) aliases string, wstring and dstring for char[], wchar[] and dchar[]Also been debated to death. No consensus yet.12) variable parrameter lists, array is created from last parrameters real average(real[...] n) {real r; for(real i in n) r+=i; return r/n.length;} // or real average(real[] n...) average(1,2,3,4,5); average([1,2,3,4,5]); // same as aboveImplementing a variant both efficiently and robustly is an unrealistic hope in a language like D.13) some type that can contain every other type (var for example) var x = 9; x = "abc"; x = new File; x = null; // type of x is now void* some mechanism for getting type of var: if(x.typeinfo == int.typeinfo) ... or more simpler: if(x is int) ... // if x is of type int Object obj = new File; if(obj is File) ...I've done something like this within D in its present form, overloading the () operator instead of throwing in an arbitrary number of commas. It doesn't look quite the same, but it does work.14) with 12 and 13 from above safer, easyer and expandable printf can be created void printf(string format, var[...] args) type info is in var[] and can be eliminated from format string: printf("int = %, real = %, string = %, object = %\n", 5, 0.2, "ba", obj) ; for objects of type class and struct member function toString() is called for printingTemplate argument deduction of some sort would solve many more problems than a specific solution like this.15) min, max and swap functions with variable parameter count for all types swap(a,b,c) {x=a; a=b; b=c; c=x;}See 'auto classes' in the spec.16) class objects on stack (vtable is not needed is this case): stack File file("..."); // create file on stackI don't see why not.17) with keyword for struct types+/- infinity seems much more useful, as you get the sign bit.18) exceptions thrown on segmentation violation error, with file and line where it occured 19) integer / and % are wrong: (-1) % 5 is 4, it is not -(1 % 5) = -1 (a%b= 0, a%b < b)real divide 1.0/0.0 should be NAN, not +INF (same for -1.0/0.0)Too much room for ambiguities. uint can be implicitly cast to real, so you would have to cast every time anyway.20) overloadable functions with diferent return types: void func() {} real func() {} uint func() {} func(); // calls first func (real)func(); // calls second func real v = (real)(uint)func(); // calls third func, and converts result to realConstructors I would very much like. Destructors don't matter to me.21) constructors and destructors for structseep.22) no commutative vesions of + and * for operator overloadingeep.23) enum Color {red, blue} Color a = red; // not Color a = Color.red;int[][] a = new int[3][5];24) multiple dimension dynamic arrays int[,] a = new int[3,5]; // 3x5 dynamic matrix a[2,2] = 3; // set one element a[1] // returns array of 5 elements from second row a.dim[0] // returns 3 a.dim[1] // returns 5 a.length // returns 3*5 a.resize(5,10) // reallocate storage for matrix, preserving old elementsCovariant return values are allowed, you know. override MyClass clone() ...25) overloadable ++ and -- operators 26) every object should have overloadable dup propertyProbably not needed. Everybody knows wht words are keywords in C, even if using other languages. Language authors do not use C keywords as identifiers unless they are completely insane.27) for identifiers same as keywords class class {int int;} // class named "class" with int named "int"I'm not sure what problem this would help solve.28) some way to extract mantisa and exponent from floating point numbers (properties?)Use a struct. :)29) fixed precision real type 32 and 64 bitsmin is always 0. max is already there, except it's called 'length'. Push and pop would be nice, but shouldn't be properties.30) exception should be thrown if mathematical error occurs class EIntZeroDivide: Exception {...} class EDomain: Exception {...} class EZeroDivide: EDomain {...} 31) properties for arrays: min, max, last, push, popI do this all the time.BUGS: 1) foreach doesn't work with inout struct as iterator 2) aliases of struct in template doesn't work when used as typesThat's a hack put in specifically because growing the array is nontrivial. I think length should be readonly, personally. A resize() method would be a better way to express array resizing. Things that look like member variables should behave like them. (ie assignment should be a trivial operation)3) ++ and -- operator doesn't work for properties: char[] a = new char[10]; a.length++; // compile errorGenuine bug, I think.4) this works, but it is an error (input-only reference is returned) Object dd(Object a) {return a;}D isn't a dynamic language, so there's not much point. There are much better scripting languages out there. What there aren't many of is languages that are fast like C++, and whose code doesn't look like something an epileptic crack addict would write to himself. :D -- andyMISC: What about interpretator and using D for scripting?
Oct 30 2003
I think named and optional function parameters could be added should be part of any statically typed language. Last it was today that I was bitten by a bug where I called someFunction(foo, bar, xyzzy, width, height) where the width and height should've actually been in different order. This wouldn't have happened if I'd had the chance to use named parameters in the first place. The Nice language developed at Inria by Daniel Bonniot is the prime example of how to do named function parameters. And if you have named parameters, you should have optional parameters, too. While you're at it, check other features, too. http://nice.sourceforge.net/manual.html#namedParameters I've only read the specs, not tried it, but here's my idea of how it works or might work. To define a function with default parameters: Window createWindow( char[] windowName = "My Window", int x, int y, int xsize = 800, int ysize = 600) { ... } Note that you needn't have the C++'ish restriction that after the first parameter that has a default value the following parameters would be forced to have them, too. But if that isn't the case, and you want to use a default value, you'll have to specify the rest of the parameters by name: main() { Window w = createWindow(x: 200, y: 200); } Also possible is the usual: createWindow("Feh", 10, 10, 640, 480); or if you want the defaults, something like createWindow("Foo", default, default, 640, 480); or maybe createWindow("Foo",,, 640, 480); // Too many possibilities for errors? You should be able to combine named and normal parameters, but the only way I could see it to be possible would be that you'd have to start with nameless params and continue with named parameters: createWindow("Foo", 10, 10, ysize: whatever); createWindow(x: 10, y: 20, 500); // What does the 500 refer to? xsize, right? createWindow(y: 10, x: 20, 500); // What about now? Maintenance nightmare! There are some things that should be thought about. Who evaluates the default parameters? Can they refer to variables that exist in the caller's scope? Can they refer to each other? I also quickly thought of the possibility to use the syntax f(y=5, x=4) when calling since it might look more natural. But it's a bit dubious since y=5 is a valid expression in itself and y looks like as if it refers to caller's scope. With ":" there is no opportunity for misunderstanding. Named parameters might also provide room for unification of constructing structs with the struct initialization syntax and calling the constructor: struct X { int a = 1; int b = 2; } X x = { a: 5, b: 6 }; If we had a) constructors, b) named function arguments and c) automatically generated constructors with named function arguments with the same names as the struct, then we'd have also: struct X { int a; int b; // default this(), implicitly generated: this(int a = 1, int b = 2) { this->a = a; this->b = b; } } and X x = X(a: 5, b: 6); Hmm, perhaps I'm getting a bit carried away. Anyway, if we also had tuples with optionally named elements, then there would no need to repeat the X there: X x = (a: 5, b: 6); Now tuples bring with themselves a load of other issues. Such as, what means (a: b, b: a)? One last idea regarding named function arguments would be an extra opportunity to overloading. Let's assume struct ctors for a second: struct Complex { // Again, this might be autogenerated and some mechanism should // maybe exist to declare that it's called by default. this(float re = 0, float im = 0) { this->re = re; this->im = im; } this(float r = 0, float theta = 0) { this->re = r * sin(theta); this->im = r * cos(theta); } float re, im; // and other stuff } main() { Complex c = Complex(1, 2); Complex d = Complex(r: 1, theta: 3.14159); } Ok, forget it - this example is rather imaginary (no pun intended) and I can't think of a real-life situation where you would do things like that except to boost your coolness factor. Certainly it's nice (no pun intended) but not probably nice enough to justify the complexity (no pun intended) of implementation and specification of the language. (Possible issues I could see would be "How to specify the default function or should it be allowed in the first place", "Should all arguments be explicitly specified if there are two alternatives or just as much as are needed to disambiguate" and "Are names of the function arguments part of its signature") On the other hand, you don't know unless you try. Experimenting a bit with the frontend and seeing how things can be made to work out might be educational. This would need a backend that you can link with, though. I wonder if Burton's backend is still in shape, the latest version seems to be a year old. -AnttiAlso nice, but not hugely so, I don't think.2) function parameters int f(int a=2, int b) {..} // default values int g(int a, int b=2) {..}... g(1); // called g(1,2); Optional parameter names in calls: f(b:6); // this is called as f(2,6);
Oct 30 2003
Yes, I like most of them... especially the array stuff. I also would like a "Pascal"-style array, i.e. with specified index value (array[index_area] of ), but I know this is not a part of the C world... Anyway, I would like an 1-based index for arrays, at least, but this is easy to do by simply dropping the first cell... I am interested in facilities to dinamically create, reshape, resize multi-dim arrays.. (coming from Matlab...) In article <oprxum0vydlucekh news.digitalmars.com>, Tintor Marko says...any comments? On Mon, 27 Oct 2003 21:10:19 +0100, Tintor Marko <elud verat.net> wrote:0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisation 1) foreach foreach(A a, B b; m) ... // multiple iterator foreach, this calls first apply foreach(A a; m) ... // second apply class M // and multiple apply functions { int apply(int delegate(A,B) dg) {...} int apply(int delegate(A) dg) {...} } for associative arrays: string[string] index ... foreach(string key, string value; index) ... (that is the use of int returned from apply?) another form: foreach(a in m) ... // easyer to read foreach(char c, int i; str) // c is every char from str, i is index of c in str int[][] a; foreach(int a; matrix) // for each element of matrix foreach(char a; "string") // for each character of string // iterating with custom functions or delegates int func(int x, delegate(int) dg) {...} foreach(int a in func(2)) ... 2) function parameters int f(int a=2, int b) {..} // default values int g(int a, int b=2) {..} ... g(1); // called g(1,2); Optional parameter names in calls: f(b:6); // this is called as f(2,6); // grouping of values in function definition int f(out int a, b, c) // same as intf(out int a, out int b, out int c) int m(int a, b, long c, d) {..} // same as int m(int a, int b, long c, long d) 3) switch case with range and multiple values: switch(x) { ... case a..b: ... // if a <= x <= b (or perhaps a <= x < b) case 1,3,5,7..9: ... ... } break is not neaded at the end of case, but can be used to early exit exception should not be thrown if case for some value is not found and there is no 'default' universal switch: any basic type, arrays (not just strings), struct, enum, class with eq() can be used in switch 4) power operator (^) for integer, real and complex numbers (~) can be used for inverting and xoring like (-) 5) word logical operators: and (&&), or (||), not(!) (it is easyer to read) not in operator: if('a' not in "ABa") instead of if(!('a' in "ABa")) 6) connected comparison operations 2 <= x < y <= 9 instead of (2 <= x) and (x < y) and (y <= 9) 7) set type (implemented as static array of bits on stack) set NAME {SYMBOL [, SYMBOL..]} [= SYMBOL [| SYMBOL..]]; // initializer for type, default is 0 (empty set) set Set {...}; Set A,B; operations: Set[i] // i+1-th symbol from set type Set[i].toString Set.max A == B // simple comparison A.count, A.max // number of elements and maximum number of elements e in A // is e element of A A in B // are all elements from A in B ~A // complement of A A | B // set union A & B // set intersection A / B // elements in A, but not in B A = 0 or A = {} // clears A A = e|d|f or A = {e,f,d} // init set with elements e, d and f &=, |=, /= oprators 8) multiple expression assert assert x>0, y>0, z>0; instead of assert(x>0); assert(y>0); assert(z>0); assert error should print entire expression that failed, line number and source file 9) arrays can be created at runtime int a[] = [1,2,4..7]; // 1,2,4,5,6,7 int b = 5; a ~= [4,b]; bar([6,9,b,b+2,5..9]); 10) compile time overlaping copies: a[0..3] = a[1..4]; a[0..3] = a[1..]; // 4 is not neaded a[0..] = a[1..4]; // 3 is not neaded 11) aliases string, wstring and dstring for char[], wchar[] and dchar[] 12) variable parrameter lists, array is created from last parrameters real average(real[...] n) {real r; for(real i in n) r+=i; return r/n.length;} // or real average(real[] n...) average(1,2,3,4,5); average([1,2,3,4,5]); // same as above 13) some type that can contain every other type (var for example) var x = 9; x = "abc"; x = new File; x = null; // type of x is now void* some mechanism for getting type of var: if(x.typeinfo == int.typeinfo) ... or more simpler: if(x is int) ... // if x is of type int Object obj = new File; if(obj is File) ... 14) with 12 and 13 from above safer, easyer and expandable printf can be created void printf(string format, var[...] args) type info is in var[] and can be eliminated from format string: printf("int = %, real = %, string = %, object = %\n", 5, 0.2, "ba", obj) ; for objects of type class and struct member function toString() is called for printing 15) min, max and swap functions with variable parameter count for all types swap(a,b,c) {x=a; a=b; b=c; c=x;} 16) class objects on stack (vtable is not needed is this case): stack File file("..."); // create file on stack 17) with keyword for struct types 18) exceptions thrown on segmentation violation error, with file and line where it occured 19) integer / and % are wrong: (-1) % 5 is 4, it is not -(1 % 5) = -1 (a%b-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/= 0, a%b < b)real divide 1.0/0.0 should be NAN, not +INF (same for -1.0/0.0) 20) overloadable functions with diferent return types: void func() {} real func() {} uint func() {} func(); // calls first func (real)func(); // calls second func real v = (real)(uint)func(); // calls third func, and converts result to real 21) constructors and destructors for structs 22) no commutative vesions of + and * for operator overloading 23) enum Color {red, blue} Color a = red; // not Color a = Color.red; 24) multiple dimension dynamic arrays int[,] a = new int[3,5]; // 3x5 dynamic matrix a[2,2] = 3; // set one element a[1] // returns array of 5 elements from second row a.dim[0] // returns 3 a.dim[1] // returns 5 a.length // returns 3*5 a.resize(5,10) // reallocate storage for matrix, preserving old elements 25) overloadable ++ and -- operators 26) every object should have overloadable dup property 27) for identifiers same as keywords class class {int int;} // class named "class" with int named "int" 28) some way to extract mantisa and exponent from floating point numbers (properties?) 29) fixed precision real type 32 and 64 bits 30) exception should be thrown if mathematical error occurs class EIntZeroDivide: Exception {...} class EDomain: Exception {...} class EZeroDivide: EDomain {...} 31) properties for arrays: min, max, last, push, pop BUGS: 1) foreach doesn't work with inout struct as iterator 2) aliases of struct in template doesn't work when used as types 3) ++ and -- operator doesn't work for properties: char[] a = new char[10]; a.length++; // compile error 4) this works, but it is an error (input-only reference is returned) Object dd(Object a) {return a;} MISC: What about interpretator and using D for scripting?
Oct 31 2003
Yes, if D had ranges, and good multidimensional array handling and array slicing, and the To Be Implemented array operations, it would come in Very Handy on many many occasions. Template syntax: Obviously Foo<T> syntax is bad for the lexer. Why not Foo(<T>) or Foo<<T>> or Foo[[T]] or Foo{T} or Foo#T or something, that wouldn't cause tokenization problems? I really don't like explicit instantiation though. It's nice to be able to when you need to, but implicit instantiation saves you so much typing. There is a fundamental philosophy of programming languages that most people are divided over: Whether they want everything to be as explicit as possible, with no ambiguities, or whether they want the compiler to do as much as possible with as little input as possible. Obviously I'm in the latter camp. ;) Sean "Felix" <Felix_member pathlink.com> wrote in message news:bnto8f$23al$1 digitaldaemon.com...Yes, I like most of them... especially the array stuff. I also would likea"Pascal"-style array, i.e. with specified index value (array[index_area]of ),but I know this is not a part of the C world... Anyway, I would like an 1-based index for arrays, at least, but this iseasy todo by simply dropping the first cell... I am interested in facilities to dinamically create, reshape, resizemulti-dimarrays.. (coming from Matlab...) In article <oprxum0vydlucekh news.digitalmars.com>, Tintor Marko says...cany comments? On Mon, 27 Oct 2003 21:10:19 +0100, Tintor Marko <elud verat.net> wrote:0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisation 1) foreach foreach(A a, B b; m) ... // multiple iterator foreach, this calls first apply foreach(A a; m) ... // second apply class M // and multiple apply functions { int apply(int delegate(A,B) dg) {...} int apply(int delegate(A) dg) {...} } for associative arrays: string[string] index ... foreach(string key, string value; index) ... (that is the use of int returned from apply?) another form: foreach(a in m) ... // easyer to read foreach(char c, int i; str) // c is every char from str, i is index ofandin str int[][] a; foreach(int a; matrix) // for each element of matrix foreach(char a; "string") // for each character of string // iterating with custom functions or delegates int func(int x, delegate(int) dg) {...} foreach(int a in func(2)) ... 2) function parameters int f(int a=2, int b) {..} // default values int g(int a, int b=2) {..} ... g(1); // called g(1,2); Optional parameter names in calls: f(b:6); // this is called as f(2,6); // grouping of values in function definition int f(out int a, b, c) // same as intf(out int a, out int b, out int c) int m(int a, b, long c, d) {..} // same as int m(int a, int b, long c, long d) 3) switch case with range and multiple values: switch(x) { ... case a..b: ... // if a <= x <= b (or perhaps a <= x < b) case 1,3,5,7..9: ... ... } break is not neaded at the end of case, but can be used to early exit exception should not be thrown if case for some value is not found and there is no 'default' universal switch: any basic type, arrays (not just strings), struct, enum, class with eq() can be used in switch 4) power operator (^) for integer, real and complex numbers (~) can be used for inverting and xoring like (-) 5) word logical operators: and (&&), or (||), not(!) (it is easyer to read) not in operator: if('a' not in "ABa") instead of if(!('a' in "ABa")) 6) connected comparison operations 2 <= x < y <= 9 instead of (2 <= x) and (x < y) and (y <= 9) 7) set type (implemented as static array of bits on stack) set NAME {SYMBOL [, SYMBOL..]} [= SYMBOL [| SYMBOL..]]; // initializer for type, default is 0 (empty set) set Set {...}; Set A,B; operations: Set[i] // i+1-th symbol from set type Set[i].toString Set.max A == B // simple comparison A.count, A.max // number of elements and maximum number of elements e in A // is e element of A A in B // are all elements from A in B ~A // complement of A A | B // set union A & B // set intersection A / B // elements in A, but not in B A = 0 or A = {} // clears A A = e|d|f or A = {e,f,d} // init set with elements e, d and f &=, |=, /= oprators 8) multiple expression assert assert x>0, y>0, z>0; instead of assert(x>0); assert(y>0); assert(z>0); assert error should print entire expression that failed, line numberbesource file 9) arrays can be created at runtime int a[] = [1,2,4..7]; // 1,2,4,5,6,7 int b = 5; a ~= [4,b]; bar([6,9,b,b+2,5..9]); 10) compile time overlaping copies: a[0..3] = a[1..4]; a[0..3] = a[1..]; // 4 is not neaded a[0..] = a[1..4]; // 3 is not neaded 11) aliases string, wstring and dstring for char[], wchar[] and dchar[] 12) variable parrameter lists, array is created from last parrameters real average(real[...] n) {real r; for(real i in n) r+=i; return r/n.length;} // or real average(real[] n...) average(1,2,3,4,5); average([1,2,3,4,5]); // same as above 13) some type that can contain every other type (var for example) var x = 9; x = "abc"; x = new File; x = null; // type of x is now void* some mechanism for getting type of var: if(x.typeinfo == int.typeinfo) ... or more simpler: if(x is int) ... // if x is of type int Object obj = new File; if(obj is File) ... 14) with 12 and 13 from above safer, easyer and expandable printf canobj)created void printf(string format, var[...] args) type info is in var[] and can be eliminated from format string: printf("int = %, real = %, string = %, object = %\n", 5, 0.2, "ba",line; for objects of type class and struct member function toString() is called for printing 15) min, max and swap functions with variable parameter count for all types swap(a,b,c) {x=a; a=b; b=c; c=x;} 16) class objects on stack (vtable is not needed is this case): stack File file("..."); // create file on stack 17) with keyword for struct types 18) exceptions thrown on segmentation violation error, with file andtowhere it occured 19) integer / and % are wrong: (-1) % 5 is 4, it is not -(1 % 5) = -1 (a%b= 0, a%b < b)real divide 1.0/0.0 should be NAN, not +INF (same for -1.0/0.0) 20) overloadable functions with diferent return types: void func() {} real func() {} uint func() {} func(); // calls first func (real)func(); // calls second func real v = (real)(uint)func(); // calls third func, and converts resultelementsreal 21) constructors and destructors for structs 22) no commutative vesions of + and * for operator overloading 23) enum Color {red, blue} Color a = red; // not Color a = Color.red; 24) multiple dimension dynamic arrays int[,] a = new int[3,5]; // 3x5 dynamic matrix a[2,2] = 3; // set one element a[1] // returns array of 5 elements from second row a.dim[0] // returns 3 a.dim[1] // returns 5 a.length // returns 3*5 a.resize(5,10) // reallocate storage for matrix, preserving oldnumbers25) overloadable ++ and -- operators 26) every object should have overloadable dup property 27) for identifiers same as keywords class class {int int;} // class named "class" with int named "int" 28) some way to extract mantisa and exponent from floating point(properties?) 29) fixed precision real type 32 and 64 bits 30) exception should be thrown if mathematical error occurs class EIntZeroDivide: Exception {...} class EDomain: Exception {...} class EZeroDivide: EDomain {...} 31) properties for arrays: min, max, last, push, pop BUGS: 1) foreach doesn't work with inout struct as iterator 2) aliases of struct in template doesn't work when used as types 3) ++ and -- operator doesn't work for properties: char[] a = new char[10]; a.length++; // compile error 4) this works, but it is an error (input-only reference is returned) Object dd(Object a) {return a;} MISC: What about interpretator and using D for scripting?-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Oct 31 2003
I really don't like explicit instantiation though. It's nice to be abletowhen you need to, but implicit instantiation saves you so much typing. There is a fundamental philosophy of programming languages that mostpeopleare divided over: Whether they want everything to be as explicit as possible, with no ambiguities, or whether they want the compiler to do as much as possible with as little input as possible. Obviously I'm in the latter camp. ;)I'm more in the former camp as a rule, but with templates it's more than just typing savings. Without explicit instantiation we're going to have an extremely hard time writing generic code.
Oct 31 2003
You mean without implicit instantiation? Sean "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message news:bnudkv$4s$1 digitaldaemon.com...asI really don't like explicit instantiation though. It's nice to be abletowhen you need to, but implicit instantiation saves you so much typing. There is a fundamental philosophy of programming languages that mostpeopleare divided over: Whether they want everything to be as explicit as possible, with no ambiguities, or whether they want the compiler to domuch as possible with as little input as possible. Obviously I'm in the latter camp. ;)I'm more in the former camp as a rule, but with templates it's more than just typing savings. Without explicit instantiation we're going to have an extremely hard time writing generic code.
Oct 31 2003
Sean L. Palmer wrote:You mean without implicit instantiation?Most of the STL and almost any other C++ template library out there relies on partial instntiation, that is only those parts of a template are generated which are immediately requiered. Some C++ compilers also allow for D-style explicit instantiation - which is always non-partial, but this practice fails. And some have supported implicit, but not partial, IIRC, which is even worse. Partial instantiation means you need not implement all of the operators/methods which a template would normally requiere, unless you are using the template so that it actually requieres them. For example, you can store objects in a vector without explicitly defining comparison for them, unless you actually need to sort them or do anything else which requieres comparison. The only way to accomplish that is to *hope* that the sort template method doesn't get instantiated, because if it does you are forced to provide a comparison. I believe this is one of the major reasons why C++ templates are so hard to get right in n implementation. The solution i would see is to partition the templates, but then you get *really* many instantiation statements, and besides i'm not exactly sure whether this would work at all in a single-inheritance environment! To remedy this, i can propose that classes are able to multiply inherit implementation from templates. Maybe also implementation-only import from other classes, which would basically make Mix-Ins? How about also templated interfaces? ... Takes me too far from my domain. Better someone with better knowledge of templates correct me. Especially Daniel, who has already done some work with D templates. -eye
Oct 31 2003
You mean without implicit instantiation?<blush>I do</blush>Sean "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message news:bnudkv$4s$1 digitaldaemon.com...ableI really don't like explicit instantiation though. It's nice to bethetoaswhen you need to, but implicit instantiation saves you so much typing. There is a fundamental philosophy of programming languages that mostpeopleare divided over: Whether they want everything to be as explicit as possible, with no ambiguities, or whether they want the compiler to domuch as possible with as little input as possible. Obviously I'm inanlatter camp. ;)I'm more in the former camp as a rule, but with templates it's more than just typing savings. Without explicit instantiation we're going to haveextremely hard time writing generic code.
Oct 31 2003
"Tintor Marko" <elud verat.net> wrote in message news:oprxum0vydlucekh news.digitalmars.com...any comments?Lots of great ideas there. Some are already in the queue to be implemented (such as the multiple parameter foreach).
Nov 01 2003
0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisationBut it doesn't fit into the language very well, does it? Perhaps something like class Foo[T] { .. } Foo[int] bar; So you have the same syntax as with D's hashs.
Oct 31 2003
On Fri, 31 Oct 2003 12:17:10 +0000 (UTC), Matthias Becker <Matthias_member pathlink.com> wrote:Why it doesn't fit?0) templates more simpler syntax T max<T>(T a, T b) {return a>b?a:b;} T max<T>(T a, T b, T c) {return max(max(a,b),c);} max(2,3); // calls max<short>(2,3) max((int)2.4f,(int)3.3f); // same class List<T> {...} class List<int> {...} // specialisationBut it doesn't fit into the language very well, does it?Perhaps something like class Foo[T] { .. } Foo[int] bar; So you have the same syntax as with D's hashs.
Oct 31 2003