Your Digital Media Has Never Looked So Good

 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Copy of Brightscript object being created when using assignment operator.

Tue Apr 18, 2017 10:29 am

In my main.brs, I am parsing a JSON from server and then assign the result which is an associative array with more nested associative arrays which house more arrays.

json = ParseJSON()
m.scene.json = json

Now, what I would expect is that it m.scene.json should be a reference to json since it is not an intrinsic object and not a copy, but a copy is being created. Any changes I make to 'json' now don't show up in m.scene.json and hence my assumption that it is a copy and not a reference. Also, after the assignment, m.scene.json become immutable and any additions that I make to the associative array fail silently.

Any ideas what I am doing wrong and what I should be doing instead?
 
User avatar
RokuNB
Posts: 106
Joined: Fri Mar 31, 2017 2:22 pm

Re: Copy of Brightscript object being created when using assignment operator.

Tue Apr 18, 2017 3:34 pm

RSG thinks different than Brightscript.
dot-access for nodes (i.e. myNode.myField) gets converted to a setValue/getValue call (depending on which side of assignment that is) and these i think always assign composite objects like roAssociativeArray and roArray "by value", in result doing deep-copy for your JSON. Nodes are assigned by reference.

When you do
m.scene.json.a = 7
the m.scene gets the node, m.scene.json returns a deep copy of the dictionary, then .a = 7 adds/assigns a key-value pair - but this is a different copy that gets modified. At the end of that statement, this copy gets disposed since nobody needs it anymore - the original m.scene.json however remains unmodified (hence "read-only")
 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Re: Copy of Brightscript object being created when using assignment operator.

Wed Apr 19, 2017 7:52 am

Thank you for your prompt response. It does clear why I seemingly had an immutable copy. But, how do I go about making changes which are persisted? Would it make sense to parse the JSON inside a new task and then assign it to the scene, but I am assuming that I will end up at the same place.

Also, if I am in the node and try to access json using m.top.json, would I get a copy again as opposed to the reference because that is what is happening currently.
 
User avatar
RokuNB
Posts: 106
Joined: Fri Mar 31, 2017 2:22 pm

Re: Copy of Brightscript object being created when using assignment operator.

Wed Apr 19, 2017 11:39 am

The response i have heard has been to use ContentNodes instead, i.e. rebuild your structure using ContentNode (or even Node if no media metadata) as a foundation for your nested structures. And that makes total sense if the data you have is either (a) multimedia item info or (b) will be used for RSG API calls (most components ask for their collections in ContentNode form).

Note that Node (roSgNode) components are passed by reference because of multi-thread-safe mechanism in them. So if convenient, their use is more efficient than deep copies.

Also note that inside a component script you could (and probably should) use the self/this variable `m` to store and mutate complex {}/[] structures.
 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Re: Copy of Brightscript object being created when using assignment operator.

Fri Apr 21, 2017 7:56 am

So, if I am getting this correctly, I should use a ContentNode for a field in the scene. Would that be different from using associative array? Would that not be immutable? Or am I completely off base?

To add to the above question, I tried the following sequence of steps

HomeScene.xml

<component name="HomeScene" extends="Scene"  xsi:noNamespaceSchemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
    <interface>
        <!-- <field id="json" type="assocarray" /> -->
       <field id="json" type="node" />


In main.brs

    m.scene.json = createObject("roSGNode", "ContentNode")

    m.scene.json.addFields({title: json.reftitle, contentList:json.contentList, backgroundUrl:json.backgroundUrl})


ContentList is an roArray type. So, while I can change the title, I can't make any changes to for ex the title field in the associative array in the ContentList array or add another item to the array. Should all the hierarchical components if they are not of intrinsic types be a ContentNode? Thanks.
 
User avatar
RokuNB
Posts: 106
Joined: Fri Mar 31, 2017 2:22 pm

Re: Copy of Brightscript object being created when using assignment operator.

Sat Apr 22, 2017 4:26 pm

parag wrote:
So, if I am getting this correctly, I should use a ContentNode for a field in the scene. Would that be different from using associative array? Would that not be immutable? Or am I completely off base?
[...]
ContentList is an roArray type. So, while I can change the title, I can't make any changes to for ex the title field in the associative array in the ContentList array or add another item to the array. Should all the hierarchical components if they are not of intrinsic types be a ContentNode? Thanks.

Using Node or ContentNode field to hold your data is different that using roAA/roArray in that yes, from your point of view node fields are mutable "in place". And yes, if you want to modify your complex structures in place, you should use Node/ContentNode instead of roAA/roArray. Would it help if in the context of node fields only you think about arrays/dictionaries as "by value" primitive types - and all roSgNode subtypes as "by reference" objects?

Why are you not using the component's `m` variable? Is it because you want to mutate a complex structure from outside?
 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Re: Copy of Brightscript object being created when using assignment operator.

Mon Apr 24, 2017 4:17 am

RokuNB wrote:
parag wrote:
So, if I am getting this correctly, I should use a ContentNode for a field in the scene. Would that be different from using associative array? Would that not be immutable? Or am I completely off base?
[...]
ContentList is an roArray type. So, while I can change the title, I can't make any changes to for ex the title field in the associative array in the ContentList array or add another item to the array. Should all the hierarchical components if they are not of intrinsic types be a ContentNode? Thanks.

Using Node or ContentNode field to hold your data is different that using roAA/roArray in that yes, from your point of view node fields are mutable "in place". And yes, if you want to modify your complex structures in place, you should use Node/ContentNode instead of roAA/roArray. Would it help if in the context of node fields only you think about arrays/dictionaries as "by value" primitive types - and all roSgNode subtypes as "by reference" objects?

Why are you not using the component's `m` variable? Is it because you want to mutate a complex structure from outside?

I am using 'm', but also want to mutate the structure from outside. What I have is a json containing a list of groups and each group has a list of videos. So, the HomeScene in this case has the parsed JSON (m.scene.json) and now when the user clicks on a video, I display the video details with a Play button. When user clicks on Play, I start playing the video, but I also want to add the video reference/details to the 'Recents' section in the parsed JSON which is where I am having trouble since my parsed copy is now immutable.
Also, if I am using Node/ContentNode, am I correct in assuming that anything that I want to stay mutable in the nested structure which is not an intrinsic type should also be a Node/ContentNode?
 
User avatar
RokuNB
Posts: 106
Joined: Fri Mar 31, 2017 2:22 pm

Re: Copy of Brightscript object being created when using assignment operator.

Mon Apr 24, 2017 9:55 am

parag wrote:
Also, if I am using Node/ContentNode, am I correct in assuming that anything that I want to stay mutable in the nested structure which is not an intrinsic type should also be a Node/ContentNode?

That's what i said - yes.
You can work around (of sorts) to that if you really, really want to by re-assigning the whole array/dictionary after every modification. Just keep in mind that's a deep copy and expensive. E.g. something like:
myJson = m.top.mySomeAssocArray ' deep copy '
recents = myJson.recent ' no deep copy, mutating this affects the source '
recents.push(newMovie)
if recents.count() > 20 then recents.shift() ' keep it trimmed down '
m.top.mySomeAssocArray = myJson ' set it back, another deep copy '
 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Re: Copy of Brightscript object being created when using assignment operator.

Mon Apr 24, 2017 10:02 am

Got it. Probably not the best idea to be copying large objects. Will try it to see that it does what I am expecting it to and then change all non-intrinsic objects to content nodes. Thanks again for your help. I might still have some more questions, but hopefully, I should be able to take it from here.
 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Re: Copy of Brightscript object being created when using assignment operator.

Mon Apr 24, 2017 4:01 pm

Can I replace an array or list with a node/ContentNode? I have got most of it working, except I am still copying the array and would like to use a reference instead.
 
belltown
Posts: 1421
Joined: Thu Dec 09, 2010 1:43 pm
Contact:

Re: Copy of Brightscript object being created when using assignment operator.

Mon Apr 24, 2017 5:28 pm

parag wrote:
Can I replace an array or list with a node/ContentNode? I have got most of it working, except I am still copying the array and would like to use a reference instead.

That would be a good idea.

It may be worth noting that you can put anything you want in a ContentNode, by extending it and adding your own fields. That will give you access to all the content item properties of the ContentNode, in addition to any properties you want to add.

For example, I have a content list, which consists of a list of items that extend a ContentNode.
<?xml version="1.0" encoding="UTF-8"?>

<component name="ContentItem" extends="ContentNode">
  <interface>
    <field id="field1" type="string" />
    <field id="field2" type="string" />
  </interface>
</component>


<?xml version="1.0" encoding="UTF-8"?>

<component name="ContentList" extends="ContentItem">
  <children>
    <ContentItem field1="Item-1" field2="Field-2" TITLE="Title-1" URL="http://url.com/1" />
    <ContentItem field1="Item-2" field2="Field-2" TITLE="Title-2" URL="http://url.com/2" />
  </children>
</component>
https://github.com/belltown/
 
parag
Topic Author
Posts: 17
Joined: Fri Mar 24, 2017 7:07 am

Re: Copy of Brightscript object being created when using assignment operator.

Tue Apr 25, 2017 8:19 am

Thanks again. I understand that I can put anything in the ContentNode, but it seems to work to replace an associative array rather than an array/list where you don't have key/value pairs. So, if I am dynamically creating an array using a contentNode, I would just create random keys and keep adding them using 'addField'? Do you see any issue?

Also, is you don't know the keys, is there a way to iterate through all the keys or simply get an array of all values like a map in java?

Who is online

Users browsing this forum: No registered users and 8 guests