Hi there -
I’m attempting to use a “primary” IdentityDictionary to keep track of a range of keys in their own, linked sub-Dictionaries.
I’ve made a very simple code demonstration below. What seems to happen is that the sub-dictionary does not update to add new values for the second key.
Does anyone know a way around this? Or why it might be happening?
Thanks.
(
var primary, secondary;
primary = IdentityDictionary.new(8);
secondary =IdentityDictionary.new(8);
secondary.put(\val1, 100.rand);
secondary.put(\val2, 100.rand);
secondary.put(\val3, 100.rand);
primary.add(\m -> secondary);
secondary.put(\val1, 100.rand);
secondary.put(\val2, 100.rand);
secondary.put(\val3, 100.rand);
primary.add(\n -> secondary);
~x= primary;
)
You are first putting data into the secondary dictionary, then saving it in the primary one under the key \m
.
Then in your second step, you’re probably thinking that you’re setting up another dictionary with different values and saving that as a separate thing under \n
.
This isn’t what’s happening.
Your second step is modifying the secondary dictionary. \m
still points to this dictionary (with new contents), so you’ll see the new values at \m
. Then you’re saving a second reference to the one-and-only secondary dictionary under \n
. But \m
and \n
both point to the same identical secondary dictionary – so naturally you will see the same contents.
If you want independent dictionaries for m and n, then you have to create independent dictionaries (either by explicitly reinitializing secondary
, or by .copy
ing before modifying, e.g., after the first primary.add
, do secondary = secondary.copy
).
hjh
1 Like
Thanks - that definitely helps, although something is still very abstract about this to me.
I’m still curious about how this would play out in an example like the following. What I would think is that the additional keys would be added to the mainRef. I’m not sure I can add .copy or reinitialize the ~mainDictionary here, though.
~mainDictionary = IdentityDictionary.new(8);
~function = {|mainRef, key|
var secondary = IdentityDictionary.new(22);
secondary.put(key++1, 100.rand);
secondary.put(key++2, 100.rand);
secondary.put(key++3, 100.rand);
~mainDictionary.add(mainRef -> secondary);
};
~function.(\test, \tones);
~function.(\test, \othertones);
~mainDictionary.postcs;
Something like this might work: I’ve adapted the function so it only creates the secondary dictionary if it doesn’t exist. Also, I’ve converted the keys to symbols – otherwise I don’t think you will be able to access them later.
You might also want to consider using a MultiLevelIdentityDictionary
- I think this can be a good use case for that.
~mainDictionary = IdentityDictionary.new(8);
~function = {|mainRef, key|
//Check if mainRef exists in main dictionary, otherwise create it
var secondary = ~mainDictionary[mainRef] ?? { IdentityDictionary.new(22) };
//Make sure the key is a symbol
secondary.put((key++1).asSymbol, 100.rand);
secondary.put((key++2).asSymbol, 100.rand);
secondary.put((key++3).asSymbol, 100.rand);
~mainDictionary.add(mainRef -> secondary);
};
~function.(\test, \tones);
~function.(\test, \othertones);
~function.(\anotherTest, \thirdTones);
~mainDictionary.postcs;
1 Like