Re: Member access of __gshared global object

2014-08-07 Thread Puming via Digitalmars-d-learn

Indeed it's confusing.

So AA is a value type that behaves like a pointer/reference.

We can add a rule to the initialization to make AA behave more 
like reference types:


If someone `refer` to an unitialized AA, that is, by doing:

```d
string[string] aa;

string[string] bb = aa; // bb `refers` to aa, by actually copying 
the AA struct.

```

They must want to use bb the same as aa, and it mostly will be 
followed by an assignment to bb (otherwise why bother refering 
it?). So we can initialize the AA BEFORE copying the struct, 
similar to the process before assigning an unitialized AA.


Actually, I think ANY structs that mimics a reference behavior 
should add this rule to really look like a reference.



On Thursday, 7 August 2014 at 02:17:19 UTC, H. S. Teoh via 
Digitalmars-d-learn wrote:
On Thu, Aug 07, 2014 at 02:00:27AM +, Puming via 
Digitalmars-d-learn wrote:

On Wednesday, 6 August 2014 at 15:42:05 UTC, Marc Schütz wrote:

[...]

Indeed, it was just what the OP suspected as the culprit.

You are right, I didn't know about the AA initialization 
problem then.


When I writln the AA and it outputs '[]', I thought it was
initialized, which in that case was actually null.

[...]

This is a known gotcha with AA's and built-in arrays: they are 
null
until you insert something into them, which means that while 
they are
null, passing them into functions that add stuff to them won't 
update
the original references because there is no common object that 
null
points to. But once they become non-empty, passing them around 
to
functions that change their contents will affect what's seen 
through the
original references, since now they are pointing at a common 
object in

memory.  So they behave like value types when null, but acquire
reference semantics once they are non-empty. This can be rather
confusing for newbies.


T




Re: Member access of __gshared global object

2014-08-07 Thread Kagamin via Digitalmars-d-learn
It's an optimization of memory allocation: you can always have a 
usable AA without allocating anything for it, so when you fill it 
with data, you may want to assign it back to where it should 
stay, similar to a slice.


Re: Member access of __gshared global object

2014-08-07 Thread Puming via Digitalmars-d-learn
Yes indeed, null initial value is reasonable. My suggestion does 
not affect that rationale, but is only based on my observation 
that if someone want to `refer` to an AA, he is more likely to 
fill it very soon, and he really mean to refer to it. These are 
similar concerns:


- create a null AA, then fill it, and the compiler/runtime will 
automatically initialize it before the fill.


- create a null AA, then refer to it (and would then use it), and 
the compiler/runtime wil automatically initialize it before the 
refer.



On Thursday, 7 August 2014 at 11:05:33 UTC, Kagamin wrote:
It's an optimization of memory allocation: you can always have 
a usable AA without allocating anything for it, so when you 
fill it with data, you may want to assign it back to where it 
should stay, similar to a slice.




Re: Member access of __gshared global object

2014-08-06 Thread via Digitalmars-d-learn

On Wednesday, 6 August 2014 at 04:14:51 UTC, Puming wrote:

On Thursday, 31 July 2014 at 10:22:28 UTC, Marc Schütz wrote:

On Thursday, 31 July 2014 at 02:03:37 UTC, Puming wrote:
1. Are AAs reference type? if so, why does the compiler copy 
it?


This is probably your problem. They are reference types, but 
initially that reference is `null`. When you write:


   auto cmds = CONFIG.commands;

`cmds` contains a copy of the `null` value. On assignment, the 
actual AA is created, and assigned to `cmds`, but not back to 
`CONFIG.commands`. Try initializing the AA in your class 
constructor.


I checked the code and could concur your suggestion.

What I found strange were:

1. The only way that I can initialize it is to assign a value. 
But I want to initialize an empty AA, is that possible?


I don't know whether there is a way currently. The obvious 
`CONFIG.commands = []` produces an error: can't have associative 
array key of void. This is likely a restriction of the current 
implementation of AAs, which is known to be suboptimal and being 
reworked slowly.




2. CONFIG.commands is not `null` before initialized, it is 
'[]'(when I writeln it).


That's just how writeln prints empty AAs. Try `writeln(cmds is 
null)`, it will print true.


But it still behave like what you described (except that it 
won't produce an NullPointer Exception.


Because the runtime checks whether they are null, and allocates 
memory if necessary.


Re: Member access of __gshared global object

2014-08-06 Thread hane via Digitalmars-d-learn

On Wednesday, 6 August 2014 at 04:14:51 UTC, Puming wrote:
1. The only way that I can initialize it is to assign a value. 
But I want to initialize an empty AA, is that possible?


workaround:

string[string] aa;
assert(aa is null);

aa[] = ;
aa.remove();
assert(aa !is null);


Re: Member access of __gshared global object

2014-08-06 Thread Dragos Carp via Digitalmars-d-learn


1. The only way that I can initialize it is to assign a value. 
But I want to initialize an empty AA, is that possible?


Like arrays, associative arrays have value semantics. This means 
that they can be always referenced.


It is easier to see this with an array:

int[] a1 = null;
writeln(a1.ptr);
writeln(a1.length);

will print null and 0;

The array is in fact a pair: ptr and length. The pair is 
allocated like any other primitive or struct and thus cannot be 
null.


This means if you want an empty AA you can write

aa1 = null;

or more explicit

aa1 = typeof(aa1).init;



2. CONFIG.commands is not `null` before initialized, it is 
'[]'(when I writeln it). But it still behave like what you 
described (except that it won't produce an NullPointer 
Exception.


See 1.


Re: Member access of __gshared global object

2014-08-06 Thread via Digitalmars-d-learn

On Wednesday, 6 August 2014 at 14:22:32 UTC, Dragos Carp wrote:


1. The only way that I can initialize it is to assign a value. 
But I want to initialize an empty AA, is that possible?


--snip--

This means if you want an empty AA you can write

aa1 = null;

or more explicit

aa1 = typeof(aa1).init;


This would defeat the purpose, see the original post.


Re: Member access of __gshared global object

2014-08-06 Thread Dragos Carp via Digitalmars-d-learn

On Wednesday, 6 August 2014 at 14:36:23 UTC, Marc Schütz wrote:


This would defeat the purpose, see the original post.


sorry, I red just the last post.

__gshared has no influence on this.


auto cmds = CONFIG.commands;
cmds[list] = new Command(...);


cmds is a thread local variable referencing the shared AA. But if 
you add new elements to cmds, cmd will be reallocated and the 
shared AA will remain unchanged. Though, updated values of 
existing keys will be visible in the original, because no 
relocation takes place.


If you want to change the original you need a pointer or a 
reference (for a setter function).


auto cmds = CONFIG.commands;
(*cmds)[list] = new Command(...);


Re: Member access of __gshared global object

2014-08-06 Thread via Digitalmars-d-learn

On Wednesday, 6 August 2014 at 15:18:15 UTC, Dragos Carp wrote:

On Wednesday, 6 August 2014 at 14:36:23 UTC, Marc Schütz wrote:


This would defeat the purpose, see the original post.


sorry, I red just the last post.

__gshared has no influence on this.


Indeed, it was just what the OP suspected as the culprit.




auto cmds = CONFIG.commands;
cmds[list] = new Command(...);


cmds is a thread local variable referencing the shared AA. But 
if you add new elements to cmds, cmd will be reallocated and 
the shared AA will remain unchanged. Though, updated values of 
existing keys will be visible in the original, because no 
relocation takes place.


This describes the semantics of regular arrays. Are you sure it 
also applies to AAs? I thought they will keep referring to the 
same data once they are initialized. But I might be mistaken...




If you want to change the original you need a pointer or a 
reference (for a setter function).


auto cmds = CONFIG.commands;
(*cmds)[list] = new Command(...);




Re: Member access of __gshared global object

2014-08-06 Thread Dragos Carp via Digitalmars-d-learn


This describes the semantics of regular arrays. Are you sure it 
also applies to AAs? I thought they will keep referring to the 
same data once they are initialized. But I might be mistaken...




This can be easily tested. And... you are right!

In the current implementation (I couldn't find any specification) 
the AA contains just a pointer[1]. I suppose that initially this 
pointer is null and on copy the pointer is copied, so that after 
initialization any change of the copy is visible in the original.


[1] 
https://github.com/D-Programming-Language/druntime/blob/master/src/rt/aaA.d#L82-85


Re: Member access of __gshared global object

2014-08-06 Thread Puming via Digitalmars-d-learn

On Wednesday, 6 August 2014 at 15:42:05 UTC, Marc Schütz wrote:

On Wednesday, 6 August 2014 at 15:18:15 UTC, Dragos Carp wrote:

On Wednesday, 6 August 2014 at 14:36:23 UTC, Marc Schütz wrote:


This would defeat the purpose, see the original post.


sorry, I red just the last post.

__gshared has no influence on this.


Indeed, it was just what the OP suspected as the culprit.


You are right, I didn't know about the AA initialization problem 
then.


When I writln the AA and it outputs '[]', I thought it was 
initialized, which in that case was actually null.








auto cmds = CONFIG.commands;
cmds[list] = new Command(...);


cmds is a thread local variable referencing the shared AA. But 
if you add new elements to cmds, cmd will be reallocated and 
the shared AA will remain unchanged. Though, updated values of 
existing keys will be visible in the original, because no 
relocation takes place.


This describes the semantics of regular arrays. Are you sure it 
also applies to AAs? I thought they will keep referring to the 
same data once they are initialized. But I might be mistaken...




If you want to change the original you need a pointer or a 
reference (for a setter function).


auto cmds = CONFIG.commands;
(*cmds)[list] = new Command(...);




Re: Member access of __gshared global object

2014-08-06 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Aug 07, 2014 at 02:00:27AM +, Puming via Digitalmars-d-learn wrote:
 On Wednesday, 6 August 2014 at 15:42:05 UTC, Marc Schütz wrote:
[...]
 Indeed, it was just what the OP suspected as the culprit.
 
 You are right, I didn't know about the AA initialization problem then.
 
 When I writln the AA and it outputs '[]', I thought it was
 initialized, which in that case was actually null.
[...]

This is a known gotcha with AA's and built-in arrays: they are null
until you insert something into them, which means that while they are
null, passing them into functions that add stuff to them won't update
the original references because there is no common object that null
points to. But once they become non-empty, passing them around to
functions that change their contents will affect what's seen through the
original references, since now they are pointing at a common object in
memory.  So they behave like value types when null, but acquire
reference semantics once they are non-empty. This can be rather
confusing for newbies.


T

-- 
Ignorance is bliss... until you suffer the consequences!


Re: Member access of __gshared global object

2014-08-05 Thread Puming via Digitalmars-d-learn

On Thursday, 31 July 2014 at 10:22:28 UTC, Marc Schütz wrote:

On Thursday, 31 July 2014 at 02:03:37 UTC, Puming wrote:
1. Are AAs reference type? if so, why does the compiler copy 
it?


This is probably your problem. They are reference types, but 
initially that reference is `null`. When you write:


auto cmds = CONFIG.commands;

`cmds` contains a copy of the `null` value. On assignment, the 
actual AA is created, and assigned to `cmds`, but not back to 
`CONFIG.commands`. Try initializing the AA in your class 
constructor.


I checked the code and could concur your suggestion.

What I found strange were:

1. The only way that I can initialize it is to assign a value. 
But I want to initialize an empty AA, is that possible?


2. CONFIG.commands is not `null` before initialized, it is 
'[]'(when I writeln it). But it still behave like what you 
described (except that it won't produce an NullPointer Exception.




Re: Member access of __gshared global object

2014-07-31 Thread Daniel Kozak via Digitalmars-d-learn
V Thu, 31 Jul 2014 02:03:35 +
Puming via Digitalmars-d-learn digitalmars-d-learn@puremagic.com
napsáno:

 Hi,
 
 I'm writing this global Config class, with an AA member:
 
 ```d
 module my.config;
 
 class Config
 {
  Command[string] commands;
 }
 
 __gshared Config CONFIG;
 ```
 
 and initialize it in another module:
 
 ```d
 module my.app;
 
 import my.config;
 
 void main()
 {
CONFIG = new Config();
CONFIG.commands[bye] = new Command(...); // add commands
 }
 ```
 
 This is OK. But when I use a local variable to hold the commands 
 AA:
 
 ```
 auto cmds = CONFIG.commands;
 cmds[list] = new Command(...);
 ```
 
 The command list is not added.
 
 I guess what happened here was that `cmds` is a threadlocal 
 variable, so the compiler somehow copied the CONFIG.commands.
 
 My questions are:
 
 1. Are AAs reference type? if so, why does the compiler copy it?
 2. How do I reference a member of __gshared global objects?

can you post code somewhere? I try it and it works for me.

module main;

import std.stdio;
import config;

void main(string[] args)
{
CONFIG = new Config();
CONFIG.commands[bye] = yep;

auto cmds = CONFIG.commands;
cmds[list] = smt;

writeln(CONFIG.commands);
// Lets the user press Return before program returns
stdin.readln();
}

module config;

class Config
{
string[string] commands;
this()
{
// Constructor code
}
}

__gshared Config CONFIG;




Re: Member access of __gshared global object

2014-07-31 Thread via Digitalmars-d-learn

On Thursday, 31 July 2014 at 02:03:37 UTC, Puming wrote:

1. Are AAs reference type? if so, why does the compiler copy it?


This is probably your problem. They are reference types, but 
initially that reference is `null`. When you write:


auto cmds = CONFIG.commands;

`cmds` contains a copy of the `null` value. On assignment, the 
actual AA is created, and assigned to `cmds`, but not back to 
`CONFIG.commands`. Try initializing the AA in your class 
constructor.


Member access of __gshared global object

2014-07-30 Thread Puming via Digitalmars-d-learn

Hi,

I'm writing this global Config class, with an AA member:

```d
module my.config;

class Config
{
Command[string] commands;
}

__gshared Config CONFIG;
```

and initialize it in another module:

```d
module my.app;

import my.config;

void main()
{
  CONFIG = new Config();
  CONFIG.commands[bye] = new Command(...); // add commands
}
```

This is OK. But when I use a local variable to hold the commands 
AA:


```
auto cmds = CONFIG.commands;
cmds[list] = new Command(...);
```

The command list is not added.

I guess what happened here was that `cmds` is a threadlocal 
variable, so the compiler somehow copied the CONFIG.commands.


My questions are:

1. Are AAs reference type? if so, why does the compiler copy it?
2. How do I reference a member of __gshared global objects?