how you build your dict determines how you can access it. why?

    Mar 21 2014 | 2:13 am
    Hi all,
    Putzing around with some nested dicts today, and I noticed something slightly odd, or at least it doesn't make sense to me -- if a dict guru can explain the reasoning, I'd love to know.  in brief:
    -- if you build nested dicts using the 'replace' message (replace foo::bar::pi  3.14) you can fish that data out with a get message to a dict. The message "get foo::bar::pi" sent to a dict will return 'foo::bar::pi  3.14', but if you send the message 'dictionary pi' to a [dict.view], you'll get an error in the max window.
    Bonus: Try dict.unpack in the same situation, and you get this: dict.unpack: unable reference dictionary named _4#%
    -- If you build an identical structure using a bunch of [dict.pack]s, the behavior is the opposite: sending the name of a sub-dict to [dict.unpack] works just fine, but 'get' messages using nesting fail.  I've enclosed a demo patch for the curious.
    Interestingly enough, if you do all your dict work in js, any dictionaries created in the script are accessible via either method.  It seems to me that all ways of building these structures should have all ways of getting information out of them available.  Intuitively, it feels like something is broken, but if there is a logic to it, then I'll shut up & figure out how to work around it...
    Max Patcher
    In Max, select New From Clipboard.

    • Mar 21 2014 | 9:25 am
      Hi !
      youve asked inside the comment about doing the same things in JS . Well ,its not quite true that you are doing it the same way . Note that in order to retrieve subkeys/dictionaries you need to use message "get" . What you will retrieve is : value (if single or array) or a dictionary (you are able to check its name with "name" attribute) . If you assign it to variable , then your variable is responsible for that received clone of a dictionary . only then you are able to provide very same API methods on that variable in order to work with it as a dictionary . Similar in Max . you need to "get" your sub dictionary first . you will retrieve its "max unique symbol name" which you can pass later to other modules as an instance .
      Max Patcher
      In Max, select New From Clipboard.
      . Im more experienced in JS environment so im not sure if we can retrieve name of a subdictionaries without formating a "get" message to our main dict . it would be much more useful than building dictionaries with pack methods first
    • Mar 21 2014 | 12:46 pm
      I'm actually banging my head against this because I did all of this in JS originally, but there is so much data passing through that it brought my patch to a grinding halt. (It's a semi-complicated structure passing about 55 values in 19 dicts, and needs to be able to do it at ~100 Hz.)
      As per your example, the 'get' message works fine when you create a structure using the replace method, and you can also get out a reference to a sub-dict. However, in theory, one should also be able to pass a reference to a sub-dict directly to a [dict.unpack] or similar _without_ getting it from the main dict, and retrieve all of the data in that sub-dict. This method works, but only when I use packs to form the dict. (look at the right-hand side of my example.)
      I also see that I had the 'get' messages slightly screwed up on the right-hand side, and I see why that method wasn't working when things are assembled with pack -- correction below. However, using pack, I can still access a sub-dict directly, which I don't seem to be able to when assembling the dicts with the 'replace' method.
      So the question is, if there are basically two methods for getting data out of dicts (be that values or references to sub-dicts), namely: -- the get method (with a 'path') -- passing a reference to a dict or sub-dict to a [dict.unpack]
      Why does option 2 not work when you use the 'replace' method to construct your dict hierarchy?
      Max Patcher
      In Max, select New From Clipboard.
    • Mar 21 2014 | 1:11 pm
      sorry i cant see the patch at the moment . Yes this is quite intriguing What i think now is that when you build your dictionaries using pack then perhaps (not sure) you are registering these dictionaries in global namespace automatically , when they are created on the fly within main Dict (literally), those are just known to your main instance (im totally guessing , but it seems logic to me).
      When you do "replace" your subsdictionary , your are creating NEW dictionary with new "unique symbol name" . you are overwriting the old namespace with new one . then perhaps old reference is gone .# EDIT -1 but it has nothing to do with our problem here# EDIT 2 perhaps it has something to do with "unique symbol name" ,which is used instead of keyname as a reference . thats why its working by passing this symbol around ,not the keyname I will investigate to make sure .
    • Mar 21 2014 | 1:55 pm
      In your first example youve been registering Dictionaries in global namespace with @name attribute . u were able to access them . if you dont do this . then you need to know its "max unique name" in order to pass around . all nested dictionaries must to be registered in order to access them separately
      In your last example you cant actually access packed Dictionaries because you are not registering them in namespace . there was mistake with your message anyway . you just had opened first patch so it reads from there . thats why uve got results .
      Max Patcher
      In Max, select New From Clipboard.
      .# EDIT in JS we are doing the same way . If we GET subdictionary , then retrieved dictionary is not a part of a global namespace as our main Dictionary . when you check its name you will see its a "max unique symbol" ,unless you create a NEW instance from it . So we are dealing with the same principles here
    • Mar 21 2014 | 2:23 pm
      Duuh. Right. It's a little confusing to me how the @name attribute in [dict.pack] works or doesn't work in tandem with the arguments to the same object. Seems like the safe thing to do is just keep those arguments consistent with the attribute.
      So what you're thinking is that when a sub-dict is created via the 'replace' method, that name isn't registered in the global namespace? Still, then, one would think that you could access sub-dicts via [dict.unpack], at least from the top level, no? But no diec there, either...
      Max Patcher
      In Max, select New From Clipboard.
    • Mar 21 2014 | 2:32 pm
      im having problems with mixed arguments in some scenarios too , it always needs to be double checked . maybe there is an issue , not sure
      "unpack" upacks values as far as i know , what you are asking is to unpack dictionary not a value here . thats why it doesnt know what to do because perhaps its not suited for it .
    • Mar 21 2014 | 2:41 pm
      as for the "replace" . it refers to every literal creation unfortunately . creating namespace for Dict is the same as placing max object with a name . look what will happen if you create Dict in max with previously packed and registered name . all data is there .
      Max Patcher
      In Max, select New From Clipboard.
      .# EDIT but when you create Dict with the same name of some literally created subdictionaries , you will still have NEW instance that will not refers to any keyname in you main Dictionary . it will be new instance in namespace
    • Mar 21 2014 | 2:50 pm
      Max Patcher
      In Max, select New From Clipboard.
      no, you can dict.unpack a sub-dict, but it uses the arguments in the dict.pack, _not_ the @name attributes of the sub-dicts. All very confusing.
    • Mar 21 2014 | 2:54 pm
      thank for pointing at unpack considering what it can retrieve
      YES confusing ! perhaps because those are plain objects (but not seen) registered within pack (@name) . seems like those not belong to dictionary . are just indexed . i would say Damn
    • Mar 21 2014 | 4:08 pm
      Yup, I see what you're saying in your 7:41 post. the data is shared. But when you say
      but when you create Dict with the same name of some literally created subdictionaries , you will still have NEW instance that will not refers to any keyname in you main Dictionary . it will be new instance in namespace
      Do you mean creating a new [dict packSubDict1] _after_ it has been instantiated in the dict.pack? if I do that, it holds the same data as the one created in the pack. However,
      I tried your idea with a 'replace' created hierarchy, but then you just wind up with 2 dicts with the same name occupying different namespaces:
      Max Patcher
      In Max, select New From Clipboard.
      I'm so accustomed in the Max world of just being able to name some data holder and getting the information anywhere, that all this gives me a headache.
    • Mar 21 2014 | 4:43 pm
      wow . but "dict.view" does ? . it means - this is dangerous . we need to keep all stuff unique ,anyway that would be confusing if used in practice . at least ive learned something , thanks for that puzzles
      # EDIT answering question . yes it was an example of what registering namespace means . it creates an instance that is max object (but not box'ed) until you do# EDIT 2 and as you see , Dict which has the same name as subdictionary of your main Dict is calling for problems
    • Mar 21 2014 | 6:50 pm
      Yes, that's why I'm hoping someone from Cycling chimes in on this thread....
    • Sep 25 2018 | 4:13 pm
      What's the upshot here? Can I do something like the code below and iterate the array?
      {"mySubDicts" : [ {"dict1" : 1},{"dict2" : 2} ] }
    • Jan 09 2020 | 11:09 am
      @AUDIOMATT I have exactly the same question. what do you get in return of a "get("mySubDicts")" message? in my case, as far as I have tried, I would get a "0 0" string. :(