Need help with List

Ryan2003

New member
Tutorial Author
Joined
Jul 12, 2020
Messages
28
Hi,

Having trouble using a list.
Hope someone can tell me what i am doing incorrectly.

Background:
I needed to pass some parameters by reference.
So, I created a class Vec2 to use for this purpose.

I pass an instance of the Vec2 class (myVec2) to a method in an instance (mytest) of a class (test).

The passed myVec2 has some basic math done to it a few times via the object ref.
Each time math is performed on it, ref is saved into a list of Vec2's (neighbors).

The issue:
Although it seems like different Vec2 values are being told to be added to the
neighbor list via .AddFirst, all that is ever seen in neighbors is the last set of data that was added.

The question:
Why are not all 3 unique Vec2's pairs of data being saved in the neighbor's list?

Code:
Import mojo

Function Main()
    New MyApp
End


Class Vec2
    Field x:INT
    Field y:INT
End


Class test

    Method FindAtRange:List<Vec2>(ref:Vec2)
        Local neighbors:List<Vec2> = New List<Vec2>
        
        ref.x += 1
        ref.y += 2
        neighbors.AddFirst(ref)
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 10 and 10 : get 10 and 10
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 10 and 10
            
        ref.x += 7
        ref.y -= 8
        neighbors.AddFirst(ref)    ' 17 and 2
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 17 and 2  : get 17 and 2
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 17 and 2
        
        ref.x -= 1
        ref.y -= 2
        neighbors.AddFirst(ref)    ' 16 and 0
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 16 and 0  : get 16 and 0
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 16 and 0
        
        Return neighbors
    
    End

End


Class MyApp Extends App
    
    Method OnCreate()
    
        Local myVec2:Vec2 = New Vec2
            
        myVec2.x = 9
        myVec2.y = 8
        
        Local mytest:test = New test
        
        Local temp:= mytest.FindAtRange(myVec2)
        
         Print(temp.First.x + " " + temp.First.y)    ' expect 16 and 0  : get 16 and 0
        Print(temp.Last.x + " " + temp.Last.y)        ' expect 10 and 10 : get 16 and 0
    
    End
    
End
 

AndyAndroid

Active member
Joined
Jun 28, 2017
Messages
120
@Ryan2003 - Seems like you should be working with FirstNode and LastNode to reference the Node vs. First and Last that will reference the Element...
 

Phil7

Administrator
CX Code Contributor
3rd Party Tool Dev
Joined
Jun 26, 2017
Messages
557
I just read through your code and noticed that you are using the same object ref for all the stuff and you are putting that object into the List each time and not the values of ref. Therefor you end up having a list filled with a reference to the same object multiple times, each reference pointing to the same value data, i.e. the result of your last calculation.

If you want to have multiple values stored in the list you need to have multiple references or objects to hold the data.
 

Ryan2003

New member
Tutorial Author
Joined
Jul 12, 2020
Messages
28
@AndyAndroid, thank you for replying.

@Phil7, thank you, I understand perfectly now what was incorrect. Your explanation of what was wrong made the figurative light bulb go off over my head.

The corrective action, however, has me struggling.
I have tried to fix the issue by adding 3 new objects (temp1, temp2, and temp3) to the code.
These object are assigned the value of ref at unique data value points.
I thought that this would work.
The result, however, is still the same as before.
Would you be so kind as to teach me what should be done?

Code:
Class test

    Method FindAtRange:List<Vec2>(ref:Vec2)
        Local neighbors:List<Vec2> = New List<Vec2>

        ref.x += 1
        ref.y += 2
        Local temp1:= ref
        neighbors.AddFirst(temp1)
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 10 and 10 : get 10 and 10
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 10 and 10
            
        ref.x += 7
        ref.y -= 8
        Local temp2:= ref
        neighbors.AddFirst(temp2)    ' 17 and 2
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 17 and 2  : get 17 and 2
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 17 and 2
        
        ref.x -= 1
        ref.y -= 2
        Local temp3:= ref
        neighbors.AddFirst(temp3)    ' 16 and 0
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 16 and 0  : get 16 and 0
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 16 and 0
        
        Return neighbors
    
    End

End
 

AndyAndroid

Active member
Joined
Jun 28, 2017
Messages
120
@Ryan2003 - You need to New each one of your vectors, looks like you are just referencing the original ref.

Code:
       Local temp1:= ref

Should be something like:

Code:
        Local temp1:Vec2 = New Vec2
        temp1.x = ref.x
        temp1.y = ref.y

Same for all your temp vector types...
 

Phil7

Administrator
CX Code Contributor
3rd Party Tool Dev
Joined
Jun 26, 2017
Messages
557
There are multiple ways to implement your approach of using one vec2 ref and modify it, then save the values in a list. If you like, I can sketch out one or two.

But maybe there is a completely different approach to the problem you are about to solve. If you describe the problem, I am sure you get some interesting input on how to get it solved.

Edit: Here are two ways to conveniently create a copy of the Vec2 object:
Code:
Import mojo

Function Main()
    New MyApp
End


Class Vec2
    
    'You can either use this constructor...
    Method New(srcVec2:Vec2)
        Self.x = srcVec2.x
        Self.y = srcVec2.y
    End
    
    '... or this copy method.
    Method Copy:Vec2()
        Local tempVec2:Vec2 = New Vec2()
        tempVec2.x = Self.x
        tempVec2.y = Self.y
        Return tempVec2
    End
    
    Field x:INT
    Field y:INT
End


Class test

    Method FindAtRange:List<Vec2>(ref:Vec2)
        Local neighbors:List<Vec2> = New List<Vec2>
        
        ref.x += 1
        ref.y += 2
        'neighbors.AddFirst(ref.Copy()) 'Uncomment this line and comment the next to see that they both work.
        neighbors.AddFirst(New Vec2(ref))
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 10 and 10 : get 10 and 10
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 10 and 10
            
        ref.x += 7
        ref.y -= 8
        'neighbors.AddFirst(ref.Copy())    ' 17 and 2
        neighbors.AddFirst(New Vec2(ref))    ' 17 and 2
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 17 and 2  : get 17 and 2
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 17 and 2
        
        ref.x -= 1
        ref.y -= 2
        'neighbors.AddFirst(ref.Copy())    ' 16 and 0
        neighbors.AddFirst(New Vec2(ref))    ' 16 and 0
            Print(neighbors.First.x + "  " + neighbors.First.y)    ' expect 16 and 0  : get 16 and 0
            Print(neighbors.Last.x + "  " + neighbors.Last.y)    ' expect 10 and 10 : get 16 and 0
        
        Return neighbors
    
    End

End


Class MyApp Extends App
    
    Method OnCreate()
    
        Local myVec2:Vec2 = New Vec2
            
        myVec2.x = 9
        myVec2.y = 8
        
        Local mytest:test = New test
        
        Local temp:= mytest.FindAtRange(myVec2)
        
         Print(temp.First.x + " " + temp.First.y)    ' expect 16 and 0  : get 16 and 0
        Print(temp.Last.x + " " + temp.Last.y)        ' expect 10 and 10 : get 16 and 0
    
    End
    
End
 
Last edited:

Ryan2003

New member
Tutorial Author
Joined
Jul 12, 2020
Messages
28
@AndyAndroid, you are correct that one of the solutions did in fact require the keyword New.
As Phil7 shows in his example, the New method was also needed to be implemented in the Vec2 class.

@Phil7, thank you for your time and the example. Very clear (now) that that is how it has to be in order for it to work.

I ran into this issue while I was working on code to find the neighboring hex cells from a given hex cell in a hexmap.
Basically, you start with a hex cell at x,y and then by predefined mathematical rules for the type of hexmap being used,
you traverse the near by neighboring cells and store their x,y values.
(e.g. start at hex cell located at 9,8. Then scan north, northeast, northwest, south, southwest, and southeast and
store the hex cell location values for those cells. If you want to go out further, e.g. 3 cells away, then just scan 3 times out in each direction
and store all of those cell locations.)

Note: The example code posted above is not the actual routine used in the hexmap computations.
Rather, it is a simplified generic representative example of what is trying to be done.
 

Ryan2003

New member
Tutorial Author
Joined
Jul 12, 2020
Messages
28
Here is the code working.
The red cell is the reference cell.
The yellow cells are all of the red cell's neighbors at a range of 3 cells away from it.
You can specify any range you like.
Thanks again everyone.
1614731301750.png
 

Phil7

Administrator
CX Code Contributor
3rd Party Tool Dev
Joined
Jun 26, 2017
Messages
557
Ok. One alternative solution came to mind. If your cells are objects that are stored in a two dimensional array, you could just put the references of the calculated cells into the neighbors:CellType list.
something like neighbors.AddFirst(hexCells[ref.x][ref.y])

This way you are avoiding the creation of those temporary objects. But I certainly don't know if this idea fits your overall design.
 
Top Bottom