Nested IdentityDIctionary Question

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 .copying 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