www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Weird hash (associative array) init behaviour?

reply Helmut Leitner <leitner hls.via.at> writes:
The following small program

  alias char[] Str;
  alias int [char []] Bag;

  Bag bag1;
  Bag bag2;

  void BagAddElem(Bag bag,Str key)
  {
    int count=bag[key];
    if(count>0) {
      bag[key]=count+1;
    } else {
      bag[key.dup]=1;
    }
  }

  int main()
  {
    int count=bag2["TEST"];

    BagAddElem(bag1,"TEST");
    BagAddElem(bag2,"TEST");

    printf("bag1.keys.length=%d\n",bag1.keys.length);
    printf("bag2.keys.length=%d\n",bag2.keys.length);

    return 0;
 }

creates the output:

  bag1.keys.length=0
  bag2.keys.length=1

Expected is:

  bag1.keys.length=1
  bag2.keys.length=1

The only difference is the first access to the two bags.
  (1) bag1 is first questioned (while still empty)
  (2) bag2 gets an element added frist

(1) seems to disable bag1 for all further accesses (this hit me
in a real world program, where 193.000 adds didn't get into the bag).

-- 
Helmut Leitner    leitner hls.via.at
Graz, Austria   www.hls-software.com
May 12 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Helmut Leitner" <leitner hls.via.at> wrote in message
news:40A23CCD.F78AD327 hls.via.at...
 The following small program

   alias char[] Str;
   alias int [char []] Bag;

   Bag bag1;
   Bag bag2;

   void BagAddElem(Bag bag,Str key)
   {
     int count=bag[key];
     if(count>0) {
       bag[key]=count+1;
     } else {
       bag[key.dup]=1;
     }
   }
Shouldn't you pass Bag as inout Bag if you are trying to change it inside the function? That is the reason that bag1 and bag2 size doesn't change.
   int main()
   {
     int count=bag2["TEST"];

     BagAddElem(bag1,"TEST");
     BagAddElem(bag2,"TEST");

     printf("bag1.keys.length=%d\n",bag1.keys.length);
     printf("bag2.keys.length=%d\n",bag2.keys.length);

     return 0;
  }

 creates the output:

   bag1.keys.length=0
   bag2.keys.length=1

 Expected is:

   bag1.keys.length=1
   bag2.keys.length=1

 The only difference is the first access to the two bags.
   (1) bag1 is first questioned (while still empty)
   (2) bag2 gets an element added frist

 (1) seems to disable bag1 for all further accesses (this hit me
 in a real world program, where 193.000 adds didn't get into the bag).

 --
 Helmut Leitner    leitner hls.via.at
 Graz, Austria   www.hls-software.com
May 12 2004
parent reply Helmut Leitner <helmut.leitner wikiservice.at> writes:
Ivan Senji wrote:
 
 "Helmut Leitner" <leitner hls.via.at> wrote in message
 news:40A23CCD.F78AD327 hls.via.at...
 The following small program

   alias char[] Str;
   alias int [char []] Bag;

   Bag bag1;
   Bag bag2;

   void BagAddElem(Bag bag,Str key)
   {
     int count=bag[key];
     if(count>0) {
       bag[key]=count+1;
     } else {
       bag[key.dup]=1;
     }
   }
Shouldn't you pass Bag as inout Bag if you are trying to change it inside the function? That is the reason that bag1 and bag2 size doesn't change.
Maybe I should use inout (I thought of it as an object pointer, not as an array reference), but bag2 *does* change through the same interface. The only difference is the initial query of bag2. -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.com
May 12 2004
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
news:40A266E1.76885A65 wikiservice.at...
 Ivan Senji wrote:
 "Helmut Leitner" <leitner hls.via.at> wrote in message
 news:40A23CCD.F78AD327 hls.via.at...
 The following small program

   alias char[] Str;
   alias int [char []] Bag;

   Bag bag1;
   Bag bag2;

   void BagAddElem(Bag bag,Str key)
   {
     int count=bag[key];
     if(count>0) {
       bag[key]=count+1;
     } else {
       bag[key.dup]=1;
     }
   }
Shouldn't you pass Bag as inout Bag if you are trying to change it inside the function? That is the reason that bag1 and bag2 size doesn't change.
Maybe I should use inout (I thought of it as an object pointer, not as an array reference), but bag2 *does* change through the same interface. The only difference is the initial query of bag2.
The statement int count=bag2["TEST"]; will add TEST to bag2 with initialized value (which is 0 for int) if it isn't already in there. An associative array has the same length field and data pointer fields as a dynamic array. So when you pass it to a function if the function either 1) calls rehash, which would reallocate the data pointer or 2) adds the first element to an unused array (the case you have here) then you should make the variable "inout" so that those changes are reflected in the original array - assuming that is what you want.
 -- 
 Helmut Leitner    leitner hls.via.at
 Graz, Austria   www.hls-software.com
May 12 2004
parent reply C <qbert atari-soldiers.com> writes:
Yes, use 'in' to determine if a key exists, and isnt 'inout' the default 
anyway ?

On Wed, 12 May 2004 14:35:01 -0400, Ben Hinkle <bhinkle mathworks.com> 
wrote:

 "Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
 news:40A266E1.76885A65 wikiservice.at...
 Ivan Senji wrote:
 "Helmut Leitner" <leitner hls.via.at> wrote in message
 news:40A23CCD.F78AD327 hls.via.at...
 The following small program

   alias char[] Str;
   alias int [char []] Bag;

   Bag bag1;
   Bag bag2;

   void BagAddElem(Bag bag,Str key)
   {
     int count=bag[key];
     if(count>0) {
       bag[key]=count+1;
     } else {
       bag[key.dup]=1;
     }
   }
Shouldn't you pass Bag as inout Bag if you are trying to change it inside the function? That is the reason that bag1 and bag2 size doesn't change.
Maybe I should use inout (I thought of it as an object pointer, not as an array reference), but bag2 *does* change through the same interface. The only difference is the initial query of bag2.
The statement int count=bag2["TEST"]; will add TEST to bag2 with initialized value (which is 0 for int) if it isn't already in there. An associative array has the same length field and data pointer fields as a dynamic array. So when you pass it to a function if the function either 1) calls rehash, which would reallocate the data pointer or 2) adds the first element to an unused array (the case you have here) then you should make the variable "inout" so that those changes are reflected in the original array - assuming that is what you want.
 --
 Helmut Leitner    leitner hls.via.at
 Graz, Austria   www.hls-software.com
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 12 2004
parent reply Andrew Edwards <edwardsac spamfreeusa.org> writes:
C wrote:
 Yes, use 'in' to determine if a key exists, and isnt 'inout' the default 
 anyway ?
No the default is 'in'!
 
 On Wed, 12 May 2004 14:35:01 -0400, Ben Hinkle <bhinkle mathworks.com> 
 wrote:
 
 "Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
 news:40A266E1.76885A65 wikiservice.at...

 Ivan Senji wrote:
 "Helmut Leitner" <leitner hls.via.at> wrote in message
 news:40A23CCD.F78AD327 hls.via.at...
 The following small program

   alias char[] Str;
   alias int [char []] Bag;

   Bag bag1;
   Bag bag2;

   void BagAddElem(Bag bag,Str key)
   {
     int count=bag[key];
     if(count>0) {
       bag[key]=count+1;
     } else {
       bag[key.dup]=1;
     }
   }
Shouldn't you pass Bag as inout Bag if you are trying to change it inside the function? That is the reason that bag1 and bag2 size doesn't change.
Maybe I should use inout (I thought of it as an object pointer, not as an array reference), but bag2 *does* change through the same interface. The only difference is the initial query of bag2.
The statement int count=bag2["TEST"]; will add TEST to bag2 with initialized value (which is 0 for int) if it isn't already in there. An associative array has the same length field and data pointer fields as a dynamic array. So when you pass it to a function if the function either 1) calls rehash, which would reallocate the data pointer or 2) adds the first element to an unused array (the case you have here) then you should make the variable "inout" so that those changes are reflected in the original array - assuming that is what you want.
 -- 
 Helmut Leitner    leitner hls.via.at
 Graz, Austria   www.hls-software.com
May 12 2004
parent reply C <qbert atari-soldiers.com> writes:
Huh thats weird, i could of swore at one time it was inout, maybe it 
changed.

Thanks

On Wed, 12 May 2004 17:24:36 -0400, Andrew Edwards 
<edwardsac spamfreeusa.org> wrote:

 C wrote:
 Yes, use 'in' to determine if a key exists, and isnt 'inout' the 
 default anyway ?
No the default is 'in'!
 On Wed, 12 May 2004 14:35:01 -0400, Ben Hinkle <bhinkle mathworks.com> 
 wrote:

 "Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
 news:40A266E1.76885A65 wikiservice.at...

 Ivan Senji wrote:
 "Helmut Leitner" <leitner hls.via.at> wrote in message
 news:40A23CCD.F78AD327 hls.via.at...
 The following small program

   alias char[] Str;
   alias int [char []] Bag;

   Bag bag1;
   Bag bag2;

   void BagAddElem(Bag bag,Str key)
   {
     int count=bag[key];
     if(count>0) {
       bag[key]=count+1;
     } else {
       bag[key.dup]=1;
     }
   }
Shouldn't you pass Bag as inout Bag if you are trying to change it inside the function? That is the reason that bag1 and bag2 size doesn't change.
Maybe I should use inout (I thought of it as an object pointer, not as an array reference), but bag2 *does* change through the same interface. The only difference is the initial query of bag2.
The statement int count=bag2["TEST"]; will add TEST to bag2 with initialized value (which is 0 for int) if it isn't already in there. An associative array has the same length field and data pointer fields as a dynamic array. So when you pass it to a function if the function either 1) calls rehash, which would reallocate the data pointer or 2) adds the first element to an unused array (the case you have here) then you should make the variable "inout" so that those changes are reflected in the original array - assuming that is what you want.
 -- Helmut Leitner    leitner hls.via.at
 Graz, Austria   www.hls-software.com
-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
May 12 2004
parent reply "Carlos Santander B." <carlos8294 msn.com> writes:
"C" <qbert atari-soldiers.com> wrote in message
news:opr7w18bltaoygh6 news.digitalmars.com
| Huh thats weird, i could of swore at one time it was inout, maybe it
| changed.
|
| Thanks
|
| On Wed, 12 May 2004 17:24:36 -0400, Andrew Edwards
| <edwardsac spamfreeusa.org> wrote:
|
|| C wrote:
||| Yes, use 'in' to determine if a key exists, and isnt 'inout' the
||| default anyway ?
||
|| No the default is 'in'!
||

For classes it is "inout". For arrays, I don't remember. For the rest, it's
"in".

-----------------------
Carlos Santander Bernal
May 12 2004
next sibling parent Ben Hinkle <bhinkle4 juno.com> writes:
Carlos Santander B. wrote:

 "C" <qbert atari-soldiers.com> wrote in message
 news:opr7w18bltaoygh6 news.digitalmars.com
 | Huh thats weird, i could of swore at one time it was inout, maybe it
 | changed.
 |
 | Thanks
 |
 | On Wed, 12 May 2004 17:24:36 -0400, Andrew Edwards
 | <edwardsac spamfreeusa.org> wrote:
 |
 || C wrote:
 ||| Yes, use 'in' to determine if a key exists, and isnt 'inout' the
 ||| default anyway ?
 ||
 || No the default is 'in'!
 ||
 
 For classes it is "inout". For arrays, I don't remember. For the rest,
 it's "in".
For all types it is "in". To see why classes aren't "inout" try void foo(Object obj){obj=null;} // change obj in caller? it shouldn't int main() { Object x = new Object(); foo(x); printf("%p\n",x); return 0; } Object references are passed by value.
 -----------------------
 Carlos Santander Bernal
May 12 2004
prev sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Carlos Santander B. wrote:

"C" <qbert atari-soldiers.com> wrote in message
news:opr7w18bltaoygh6 news.digitalmars.com
| Huh thats weird, i could of swore at one time it was inout, maybe it
| changed.
|
| Thanks
|
| On Wed, 12 May 2004 17:24:36 -0400, Andrew Edwards
| <edwardsac spamfreeusa.org> wrote:
|
|| C wrote:
||| Yes, use 'in' to determine if a key exists, and isnt 'inout' the
||| default anyway ?
||
|| No the default is 'in'!
||

For classes it is "inout". For arrays, I don't remember. For the rest, it's
"in".

-----------------------
Carlos Santander Bernal


  
To be more specific. Everything is passed as *in* by default. Its just that arrays and classes are references that allows you be able to modify the data and pass it back. For instance, what does this do? class A { void func() { } } void func(A a) { a = new A; } int main( char[][] args ) { A a; func(a); a.func(); return 0; } -- -Anderson: http://badmama.com.au/~anderson/
May 13 2004