digitalmars.D - what prevents dynamic array from being deprecated & tuple being
- davidl (67/67) Apr 01 2009 Something like following can substitute dynamic array:
- davidl (8/75) Apr 02 2009 the curry example needs symbol level operator overloading.
- Trass3r (3/10) Apr 02 2009 Can't understand what's so ugly about that. int~float is nothing better.
- bearophile (7/13) Apr 03 2009 On 32 bit systems that struct is 3*4 bytes long, but the current GC allo...
- Andrei Alexandrescu (3/12) Apr 04 2009 Aren't arrays manipulated mostly by value?
Something like following can substitute dynamic array: struct da(T){ T* ptr; int len, capacity; T opIndex(int i){} int length(){ return len;} void length(int len){ // do allocation} this(int i){ //allocate memory for ptr } this(){ // do nothing} da!(T) opCat(T* a){ //do concat } da!(T) opCat_r(T* a){ //do concat } da!(T) opCat(T c){ //do concat } da!(T) opCat_r(T c){ //do concat } opAssign(T* p) {} opAssign(da!(T) da) {} da!(T) opMul(int i) {} da!(T) opMul(da!(T) i) {} // some dot product ? da!(T) opDiv(da!(T) i) {} } auto myda = da!(int)(3) auto p = da!(int)(); p = myda~3; The cons/pros of this proposal: Cons: ungly syntax da!(int)(3) is really worse than int[3]; slow down the compiling process Pros: We can extend dynamic array without D2 feature of alias This Also Tuple!(int, float) is accused as ugly I believe the metatype programming system here not yet fully exploited. The template matching is powerful, but the syntax is aweful. how about the following beautify of da!(int)(3) and tuple!(int,float) type(T) // overload all types { opIndex(int v) { type = da!(T)(v) // we directly meta program the type system } opIndex(U) { // associate array, assume we created some associate array struct template named Aa type = Aa!(U, T) } opCat(U) { type = Tuple!(T,U); } } then we can do : int[3] => type(int) opIndex(int v) then further resolve the type to be da!(int)(3) int~float => type(int) opCat(float) , therefore further resolve the type to be Tuple!(int, float) I think tuple of int~float is quite acceptable With this directly metaprogramming, we can solve series of issues all together. We can define a matrix by int^int or float^float Imagine: int^int mat= new int^int(3,4); int[4] p; auto v= mat*p; // we can do a lot compile time check in the compiletime type syntax meta programming We can define function curry as: f^g h; h(3) will eventually become f(g(3)); We can do a lot more new things!! :)
Apr 01 2009
在 Thu, 02 Apr 2009 12:08:39 +0800,davidl <davidl 126.com> 写道:Something like following can substitute dynamic array: struct da(T){ T* ptr; int len, capacity; T opIndex(int i){} int length(){ return len;} void length(int len){ // do allocation} this(int i){ //allocate memory for ptr } this(){ // do nothing} da!(T) opCat(T* a){ //do concat } da!(T) opCat_r(T* a){ //do concat } da!(T) opCat(T c){ //do concat } da!(T) opCat_r(T c){ //do concat } opAssign(T* p) {} opAssign(da!(T) da) {} da!(T) opMul(int i) {} da!(T) opMul(da!(T) i) {} // some dot product ? da!(T) opDiv(da!(T) i) {} } auto myda = da!(int)(3) auto p = da!(int)(); p = myda~3; The cons/pros of this proposal: Cons: ungly syntax da!(int)(3) is really worse than int[3]; slow down the compiling process Pros: We can extend dynamic array without D2 feature of alias This Also Tuple!(int, float) is accused as ugly I believe the metatype programming system here not yet fully exploited. The template matching is powerful, but the syntax is aweful. how about the following beautify of da!(int)(3) and tuple!(int,float) type(T) // overload all types { opIndex(int v) { type = da!(T)(v) // we directly meta program the type system } opIndex(U) { // associate array, assume we created some associate array struct template named Aa type = Aa!(U, T) } opCat(U) { type = Tuple!(T,U); } } then we can do : int[3] => type(int) opIndex(int v) then further resolve the type to be da!(int)(3) int~float => type(int) opCat(float) , therefore further resolve the type to be Tuple!(int, float) I think tuple of int~float is quite acceptable With this directly metaprogramming, we can solve series of issues all together. We can define a matrix by int^int or float^float Imagine: int^int mat= new int^int(3,4); int[4] p; auto v= mat*p; // we can do a lot compile time check in the compiletime type syntax meta programming We can define function curry as: f^g h; h(3) will eventually become f(g(3)); We can do a lot more new things!! :)the curry example needs symbol level operator overloading. type overloading can allow: -int <-- which might be overloaded to type of anything without int. int[int~int] thus mean two dimensional associate array. int[int~float] p; p[3~2.5]= 3; In all, this makes a lot of things with much better syntax.
Apr 02 2009
davidl schrieb:The cons/pros of this proposal: Cons: ungly syntax da!(int)(3) is really worse than int[3]; slow down the compiling processYep, you say it.Also Tuple!(int, float) is accused as uglyCan't understand what's so ugly about that. int~float is nothing better.
Apr 02 2009
davidl:Something like following can substitute dynamic array: struct da(T){ T* ptr; int len, capacity; T opIndex(int i){} ...On 32 bit systems that struct is 3*4 bytes long, but the current GC allocates small sizes using blocks of memory long as powers of 2, so I think that struct uses 4*4 bytes anyway. So the 4th word can be used for something else. A good way to use it may be to store there a hash value (by default is 0, that means "hash not computed yet"). Hash values are really useful, especially for immutable arrays/strings, because for example to tell two strings are equal you can first compare their pointer and length, and then their hash values. If the hash values are present, then most of the times you can tell if they are different. Having hash values is very useful for AA keys/set items too, because for example to compute the intersection among things that have a hash value, you can use the hash value to see if they are different in a very quickly way. So your set operations become very fast (this is how Python set operations work). Hash values for strings can be useful for the GC too. Some people have shown that in long-running Java programs many strings are duplicated. So if you have immutable strings you can store only one copy of a string, saving lot of memory. The GC can perform such compaction using the hash values to speed up the tests necessary to see if two strings are different. Bye, bearophile
Apr 03 2009
bearophile wrote:davidl:Aren't arrays manipulated mostly by value? AndreiSomething like following can substitute dynamic array: struct da(T){ T* ptr; int len, capacity; T opIndex(int i){} ...On 32 bit systems that struct is 3*4 bytes long, but the current GC allocates small sizes using blocks of memory long as powers of 2, so I think that struct uses 4*4 bytes anyway. So the 4th word can be used for something else. A good way to use it may be to store there a hash value (by default is 0, that means "hash not computed yet").
Apr 04 2009