www.digitalmars.com         C & C++   DMDScript  

D - Ideas for D

reply Tintor Marko <elud verat.net> writes:
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
next sibling parent davepermen <davepermen_member pathlink.com> writes:
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
prev sibling next sibling parent reply Tintor Marko <elud verat.net> writes:
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: http://www.opera.com/m2/
Oct 30 2003
next sibling parent reply Andy Friesen <andy ikagames.com> writes:
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
Oct 30 2003
parent Antti =?iso-8859-1?Q?Syk=E4ri?= <jsykari gamma.hut.fi> writes:
 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
Oct 30 2003
prev sibling next sibling parent reply Felix <Felix_member pathlink.com> writes:
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: http://www.opera.com/m2/
Oct 31 2003
parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
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: http://www.opera.com/m2/
Oct 31 2003
parent reply "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
 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.
Oct 31 2003
parent reply "Sean L. Palmer" <palmer.sean verizon.net> writes:
You mean without implicit instantiation?

Sean

"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:bnudkv$4s$1 digitaldaemon.com...
 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.
Oct 31 2003
next sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
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
prev sibling parent "Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
 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...
 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.
Oct 31 2003
prev sibling parent "Walter" <walter digitalmars.com> writes:
"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
prev sibling parent reply Matthias Becker <Matthias_member pathlink.com> writes:
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.
Oct 31 2003
parent Tintor Marko <elud verat.net> writes:
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.
Oct 31 2003