1

The output from the following code does not behave how I think it should. It appears that making changes to the string array returned by testAA.require() does not reflect in the associative array. I thought dynamic arrays were pass by reference, but this seems to be behaving contrary to this notion. Re-assigning the array to testAA does appear to work, but the reason why this does not work is bothering me. Any tips or ideas would be appreciated!

module main;

import std.stdio;

void main()
{
  string[][string] testAA;
  string[] vals = ["InitVal1", "InitVal2"];

  auto list = testAA.require("Key", vals);

  writeln("list: ", list);

  list ~= "Val1";
  list ~= "Val2";

  writeln("list: ", list);
  writeln("testAA", testAA);
}

This results in the output:

list: ["InitVal1", "InitVal2"]
list: ["InitVal1", "InitVal2", "Val1", "Val2"]
testAA["Key":["InitVal1", "InitVal2"]]

3 Answers 3

2

The call to update isn't necessary after the require, just do testAA["Key"] ~= "Val1". Note that this does not update list, which is again, still a copy of the array slice at the time it was added.

If you want to do it by reference, you need to use a pointer:

auto list = &testAA.require("Key", vals); // keep a pointer to the array
*list ~= "Val1";
*list ~= "Val2";

If I'm unsure if an AA has a key, I usually will do aa.require(key) ~= val;. This is a bit less nice than just indexing, but basically equivalent to indexing, putting in a value.init when it doesn't yet exist.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome! Did not think to use ~= operator directly on the associative array. Whats more, just doing a "testAA["Key"] ~= "Val1";' works even when the key is not yet set. Still a little bit of a mystery to me how this all occurs, but that's rather elegant none-the-less. Thanks!
1

Someone pointed me to using the associative array update() method and also explained that a slice (dynamic array) consists of a pointer and a length, which are copied, even though the content itself is referenced. So the slice in the associative array does not update when the slice is updated external to it.

So I used this to create a new list with a single item or append a value to the list if it already exists:

testAA.update("Key", () => ["Val1"], (ref string[] x) {x ~= "Val1";});

Comments

0

Where in the docs does it say that associate arrays are passed by ref? If you want a ref, your function should have the ref keyword in the function signature. It's the same thing with normal arrays.

3 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
"Pass by ref" as in a pointer, not the keyword "ref". Data types are either pass by value (gets copied) or pass by reference (a pointer). Associative arrays do indeed get passed by reference to functions. Dynamic arrays (slices) don't. For example this function does assign a new value to the associative array parameter: void setmap(int[string] map, string key, int val) { map[key] = val; } Whereas this function does not append a value to an array, since it is passed by value: void arrayAppend(int[] arr, int val) { arr ~= val; }

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.