www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - what prevents dynamic array from being deprecated & tuple being

reply davidl <davidl 126.com> writes:
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
next sibling parent davidl <davidl 126.com> writes:
在 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
prev sibling next sibling parent Trass3r <mrmocool gmx.de> writes:
davidl schrieb:
 The cons/pros of this proposal:
 Cons:
 ungly syntax   da!(int)(3) is really worse than int[3];
 slow down the compiling process
 
Yep, you say it.
 Also Tuple!(int, float) is accused as ugly
 
Can't understand what's so ugly about that. int~float is nothing better.
Apr 02 2009
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 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").
Aren't arrays manipulated mostly by value? Andrei
Apr 04 2009