top | item 46335863

(no title)

nickcw | 2 months ago

I wonder if the compiler really needs to allocate 1 byte so you can get the address of the struct {}

In the general case then yes, but here you can't take addresses of dictionary values (the compiler won't let you) so adding 1 byte to make a unique pointer for the struct {} shouldn't be necessary.

Unless it is used in the implementation of the map I suppose.

So I conjecture a bit of internal magic could fix this.

discuss

order

occamrazor|2 months ago

I’m curious, what was the rationale for forbidding it?

kbolino|2 months ago

I interpret this as asking "why can't you get the address of a value in a map?"

There are two reasons, and we could also ask "why can't you get the address of a key in a map?"

The first reason is flexibility in implementation. Maps are fairly opaque, their implementation details are some of the least exposed in the language (see also: channels), and this is done on purpose to discourage users of the language from mucking with the internals and thus making it harder for the developers of the language to change them. Denying access to internal pointers makes it a lot easier to change the implementation of a map.

The second reason is that most ways of implementing a map move the value around copiously. Supposing you could get a pointer p := &m[k] for some map m and key k, what would it even point to? Just the value position of a slot in a hash table. If you do delete(m, k) now what does it point to? If you assign m[k2] but hash(k2) == hash(k) and the map handles the collision by picking a new slot for k, now what does it point to? And eventually you may assign so many keys that the old hash table is too small and so a new one somewhere else in memory has to be allocated, leaving the pointer dangling.

While the above also apply to pointers-to-keys, there is another reason you can't get one of those: if you mutated the key, you would (with high probability) violate the core invariant of a hash table, namely that the slot for an entry is determined exactly by the hash of its key. The exact consequences of violating this would depend on the specific implementation, but they are mostly quite bad.

For comparison, Rust, with its strong control over mutability and lifetimes, can give you safe references to the entries of a HashMap in a way Go cannot.