If I want to have a function modify an associative array argument, when must I pass it by `ref` and when is it okay not to?

Concrete example;

```d
import std;

void modifyByRef(AA : V[K], V, K)(ref AA aa)
{
    aa[K.init] = V.init;
}

void modifyNoRef(AA : V[K], V, K)(/*ref*/ AA aa)
{
    aa[K.init] = V.init;
}

auto uniqueKey(AA : V[K], V, K)
    (/*ref*/ AA aa,
    K min = 1,
    K max = K.max,
    V value = V.init)
{
    auto id = uniform(min, max);
    while (id in aa) id = uniform(min, max);

    aa[id] = value;
    return id;
}

void main()
{
    int[int] aa;
    assert(0 !in aa);
    modifyByRef(aa);
    assert(0 in aa);

    int[int] aa2;
    assert(0 !in aa2);
    modifyNoRef(aa2);
    assert(0 in aa2);

    int[int] aa3;
    const key = aa3.uniqueKey;
    assert(key in aa3); // <--
}

```

The `key in aa3` assert fails unless I make `uniqueKey` take its argument by ref. But `modifyNoRef` manages just fine without it. They work on the same type and they're all templates. The AAs they are passed have not been assigned any prior values.

What is the deciding difference between those two functions?

Reply via email to