[RESOLVED]List inside list problem

froz

  • Posts: 250
Sorry for very general topic name, I couldn't find better one.


I have a problem/question concerning lists. I have a code similar to this:

Code: [Select]
set listA to create new list
set listB to create new list
set listB to split [2,2,0,-1] using separator [,]
print listA
replace item #2 with -1 in listB
add listB to listA
print listA
replace item #2 with 1 in listB
print listA
empty listB
print listA

Now, I was pretty sure that this code should print this result:

Code: [Select]
2,2,0,-1
2,2,0,-1,2,2,-1,-1
2,2,0,-1,2,2,-1,-1,2,2,1,-1
2,2,0,-1,2,2,-1,-1,2,2,1,-1

However, I get this:

Code: [Select]
2,2,0,-1
2,2,-1,-1,2,2,-1,-1
2,2,1,-1,2,2,1,-1,2,2,1,-1
,,

Can anyone explain to me why does it happen? Why are items in listA affected by changes to listB that were made after listB was put in listA. I thought that when you put an item in a list, you don't really put the attribute itself there, but only the value of that attribute. So when you change the attribute later, it won't change the value inside the list. And I have pages of code that work like this. But not in this case.



Edit: Just after finishing this post I checked something. Using "set listB" kind of fix this. I mean this block will change listB, but will not change any item in listA, while "replace item x in listB" and "empty listB" will change items already saved in listA. I really don't get it.

« Last Edit: October 19, 2012, 03:01:24 pm by froz »

captaincomic

  • *
  • Posts: 6109
I think what's happening is this: When you "add listB to listA" you are not adding the elements in listB to listA, but you are adding the actual list. It looks like when you print the lists it doesn't show that it's a list inside a list.

froz

  • Posts: 250
Yes, from my example it looks like that. But should it work like that?

And why it stops working like that when I use "set listB" block? Why isn't this block changing the listB inside listA? And why does it only work like this with lists, not with number attributes? When I add a number attribute to the list and then I change this attribute in any way, it won't affect the list at all.

captaincomic

  • *
  • Posts: 6109
Yes, from my example it looks like that. But should it work like that?
Yes, I think that's how AS3 works. It is kind of explained here: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f56.html
(it's about passing variables to functions, but it also applies to adding variables to lists)
Quote
In many programming languages, it’s important to understand the distinction between passing arguments by value or by reference; the distinction can affect the way code is designed.

To be passed by value means that the value of the argument is copied into a local variable for use within the function. To be passed by reference means that only a reference to the argument is passed instead of the actual value. No copy of the actual argument is made. Instead, a reference to the variable passed as an argument is created and assigned to a local variable for use within the function. As a reference to a variable outside the function, the local variable gives you the ability to change the value of the original variable.

In ActionScript 3.0, all arguments are passed by reference, because all values are stored as objects. However, objects that belong to the primitive data types, which includes Boolean, Number, int, uint, and String, have special operators that make them behave as if they were passed by value

In short: Lists (Arrays) are passed by reference, there is no copy of the list created, but you are adding just a reference of listB to listA. But numbers are passed by value. If you add a number to a list, only the value is added, not a reference to the Number object.

And why it stops working like that when I use "set listB" block? Why isn't this block changing the listB inside listA?
If you use the "set listB" block you are setting listB to a different list, but leaving the old list (referenced from listA) intact.
So after
"add listB to listA"
"set listB to create new list"
the original listB is still in listA, while listB contains a new list.

froz

  • Posts: 250
Thanks for taking your time to write that. I really appreciate it. I think I know understand how it works.


However, I have another problem which is probably related, so I don't want to start a new topic. I hope you can help me with this one too.

I know have my listA, which has 3 items - each one is a different version of listB, created with "set listB" block.

I have another list, let's call it listC. It contains 4 numbers, just like listB.

I want to check if listA contains the list that is identical to listC. How can I do that?

Block <list contains anything> doesn't work in this case, as well as using <for each item in the listB <if item = listC>>. I'm guessing that's because it's not comparing numbers, but lists and it just sees that they are different.

Strangely though, it does work when (in another part of my code) I compare listC to text attribute (this attribute has a format similar to list, for example: 1,2,3,4). Is this the only way to make it work?

Sunflower

  • Posts: 591
First of all: yes, you're correct. When you add a list to another list, you're keeping "this particular list which might change over time", not "a list which contains items 1, 2, 3, 4 and it doesn't matter which list is that". Those list are kind of like Actors, but without Actors. I mean... uhh, forget about that analogy! ^^'

Second: if I were to compare the contents of two lists, I would do some loop checking equality of items at proper indices and probably pack it in a custom blocks. Though I suppose comparing the list to the text might be actually "neater", though probably some hardcore programmers would complain about it not being in proper coding style and such, especially with such unusual casting! :P

OR you can use the ArrayUtil function from Stencyl API. As far as I know, the code in API is rather safe update-to-3.0 wise though I might be wrong here. And you might pack it in global custom block so you wouldn't need to type it every damn type you would want to; after all, the whole idea behind DM is that you need to type things manually only as much as necessary!

The global custom block would have Boolean return value and "One List" and "Another List" list-type fields. Specification would probably make sense to be like "lists %0 and %1 are identical", and the only contents would be code block containing the following:
ArrayUtil.arraysAreEqual(__OneList, __AnotherList);
(note the double underscore!)

And why making it global? Because you won't need to attach some behavior to every scene where you could possibly use such check. Yay!

...hope this helps? ^^'

froz

  • Posts: 250
Great, thanks. That's something I was looking for (the ArrayUtil function). I don't have time to check it right now, but I should be ok.

froz

  • Posts: 250
Ok, everything works. It wasn't at first, until I realized that "split text" returns a list of text items, not numbers. It's funny though when I see "1,2,3,4 is not the same as 1,2,3,4" printed in console :D .

Anyway, finally I managed to make it work. Thanks again to both of you. By the way, I'm using your 2d array  behaviour, Sunflower. Very helpful :) .