# B4J QuestionFor Each/Next List of Maps and references. What am I misunderstanding?

#### OliverA

##### Expert
B4J Version: 7.51
OS Platfrom: Win10 Pro (1903)

Here's the setup. I'm creating a list of maps that contain x, y values (note: in my case, the map contains way more info, I'm just simplifying it here to show the issue I'm running into)
B4X:
``````    Dim largestX As Int = 4
Dim mapList As List
mapList.Initialize
For x = 0 To largestX
Dim aMap As Map
aMap.Initialize
aMap.Put("x", x)
aMap.Put("y", x+1)
Next
Log("Dump of mapList:")
For Each tempMap As Map In mapList
Log(\$"(x,y) = (\${tempMap.Get("x")},\${tempMap.Get("y")})"\$)
Next``````
Output:
Dump of mapList:
(x,y) = (0,1)
(x,y) = (1,2)
(x,y) = (2,3)
(x,y) = (3,4)
(x,y) = (4,5)
Now I'm going to try to find the map that contains the smallest x amount:
B4X:
``````    Log("Let's find the smallest x value. It should be 0")
Dim smallestXmap As Map
Dim smallestX As Int = largestX
For Each temp2Map As Map In mapList
If temp2Map.Get("x") < smallestX Then
Log("Found a smaller x!")
smallestX = temp2Map.Get("x")
smallestXmap = temp2Map
End If
Next
Log(\$"Smallest x value is \${smallestX}"\$)
Log("The log entry below should show content of (0,1), but it does not. Why?")
Log(\$"Map containing smallest x value has following content: (\${smallestXmap.Get("x")},\${smallestXmap.Get("y")})"\$)``````
And the ouput is:
Let's find the smallest x value. It should be 0
Found a smaller x!
Smallest x value is 0
The log entry below should show content of (0,1), but it does not. Why?
Map containing smallest x value has following content: (4,5)
Why? Why are the contents of smallestXmap 4,5? If temp2Map is just a reference and stays the same, then why does the following code work?
B4X:
``````    'https://www.b4x.com/android/forum/threads/maps-for-each-but-backwarts-like-step-1.64131/#post-405821
Log("The list below is produced properly. What is the difference (besides code)?")
Dim itemsToRemove As List
itemsToRemove.Initialize
For Each temp3Map As Map In mapList
If temp3Map.Get("x") > 0 And temp3Map.Get("x") < largestX Then
End If
Next
For Each temp4Map As Map In itemsToRemove
Log(\$"Map with content (\${temp4Map.Get("x")}, \${temp4Map.Get("y")}) flagged for removal"\$)
Next``````
Output:
The list below is produced properly. What is the difference (besides code)?
Map with content (1, 2) flagged for removal
Map with content (2, 3) flagged for removal
Map with content (3, 4) flagged for removal
Would I not be adding the same temp3Map reference to the list and get (3,4) for all three logs?
And why does this modified version produce a correct output if an intermediate list is used?
B4X:
``````    Log("Let's find the smallest x value, try#2. It should be 0")
Dim smallestXmap2 As Map
Dim smallestX2 As Int = largestX
Dim smallestXList As List
smallestXList.Initialize
For Each temp5Map As Map In mapList
If temp5Map.Get("x") < smallestX2 Then
Log("Found a smaller x!")
smallestX2 = temp5Map.Get("x")
smallestXmap2 = temp5Map
smallestXList.Set(0,temp5Map)
'Just for kicks
smallestXList.Set(1,smallestXmap2)
End If
Next
Log(\$"Smallest x value is \${smallestX2}"\$)
Log("The log entry below should show content of (0,1), but it does not. Why?")
Log(\$"Map containing smallest x value has following content: (\${smallestXmap2.Get("x")},\${smallestXmap2.Get("y")})"\$)
Log("Extracting map from smallestXList list")
Dim lastTempMap As Map
lastTempMap = smallestXList.Get(0)
Log(\$"Map containing smallest x value has following content: (\${lastTempMap.Get("x")},\${lastTempMap.Get("y")})"\$)
Log("Why did this work?")
Dim justForFun As Map
justForFun = smallestXList.Get(1)
Log("Retrieving smallestXmap2 from list")
Log(\$"Map containing smallest x value has following content: (\${justForFun.Get("x")},\${justForFun.Get("y")})"\$)
Log("This works too!!! I'm confused (Note: It should, but then why does the previous smallestXmap2 log produce it's result?).")``````
Output:
Let's find the smallest x value, try#2. It should be 0
Found a smaller x!
Smallest x value is 0
The log entry below should show content of (0,1), but it does not. Why?
Map containing smallest x value has following content: (4,5)
Extracting map from smallestXList list
Map containing smallest x value has following content: (0,1)
Why did this work?
Retrieving smallestXmap2 from list
Map containing smallest x value has following content: (0,1)
This works too!!! I'm confused (Note: It should, but then why does the previous smallestXmap2 log produce it's result?).
Program terminated (StartMessageLoop was not called).
What am I not seeing/understanding? I've lost over 1/2 of a day on this and it's bugging me.

#### Attachments

• 20190909_ForNextObjectsTest.zip
1.6 KB · Views: 153

#### OliverA

##### Expert
There is a hint in there.... (init)
You're going to need to use a sledgehammer on me, I'm currently that dense. I just don't see it. I need my face rubbed into it. It's pretty sad and frustrating that I just don't get it.

#### EnriqueGonzalez

##### Well-Known Member
Longtime User
i think i get it...

it is related to memory pointers....

B4X:
``For Each temp2Map As Map In mapList``
this one is is iterating over each temp2map and asigning different pointers to temp2map.

when you do this:

B4X:
``smallestXmap = temp2Map``

you are saying that smallestXmap is pointing to the same memory address as temp2map.

with primitives you dont get that issue, primitives are compared for their value but complex strucutures are compared to their memory address....

change it like this:

B4X:
``````    For i = 0 To mapList.Size -1
Dim temp2Map As Map = mapList.Get(i)``````

you will get your expected value.

why? easy.. now each temp2map is now getting different map pointers each time, not reasigning the pointer to the variable.

#### OliverA

##### Expert
you are saying that smallestXmap is pointing to the same memory address as temp2map.

smallestXList.Set(0,temp5Map)
Then why is this working? Technically I'm saying that List item #0 is temp5Map, a pointer. Therefore at the end it should also produce the incorrect result, but it does not.

If temp3Map.Get("x") > 0 And temp3Map.Get("x") < largestX Then
End If
How does this work then? I'm not doing a Dim temp3Map as Map = mapList.Get(i) here, yet each Add adds a different map, instead of a pointer that in the end points to the same map.

#### EnriqueGonzalez

##### Well-Known Member
Longtime User
I do not see how the 2 examples are related. On the items to remove you are deleting that specific pointer. If later the pointer is reassigned doesn't mean it's going to be deleted automatically.

Maybe the difference of the 3 examples is that on the first you are not calling any function. On the second you are calling to functions. Remove and set.

Functions can handle pointers but only the one you are passing not every time you reassign a pointer.

#### OliverA

##### Expert
Functions can handle pointers but only the one you are passing not every time you reassign a pointer.
Interesting.
B4X:
``````Sub returnMap(aMap As Map) As Map
Dim secondMap As Map
secondMap = aMap
Return secondMap
End Sub

Sub returnMap2(aMap As Map) As Map
Dim aList As List
aList.Initialize
Return(aList.Get(aList.IndexOf(aMap)))
End Sub

Sub returnMap3(aObject As Object) As Map
Dim secondMap As Map
secondMap = aObject
Return secondMap
End Sub

Sub returnMap4(aObject As Object) As Map
Return aObject
End Sub``````

Usage example: smallestMap = returnMap(temp2Map)

returnMap produces the same erroneous result, but returnMap2, returnMap3, and returnMap4 work.

And yes, for each/next is just like doing a for x = without redimming the temp map:
B4X:
``````    Dim temp6Map As Map
Dim smallestXmap3 As Map
Dim smallestX3 As Int = largestX
For x = 0 To largestX
temp6Map = mapList.Get(x)
If temp6Map.Get("x") < smallestX3 Then
Log("Found a smaller x!")
smallestX3 = temp6Map.Get("x")
smallestXmap3 = temp6Map
End If
Next``````

It's interesting that passing the map as an object to a method and returning it as a map correctly de-references the map. I guess I've never used a for each next loop without assigning the object retrieved with the each clause to a list, and therefore never ran into this problem. BTW, this works when using For Each/Next:
B4X:
``````    Log("Let's find the smallest x value. It should be 0")
Dim tempMap98 As Map
Dim smallestXmap99 As Map
Dim smallestX99 As Int = largestX
For Each tempObject As Object In mapList       ' Retrieve items from list as Object
tempMap98 = tempObject                          ' Cast Object to Map
If tempMap98.Get("x") < smallestX99 Then
Log("Found a smaller x!")
smallestX99 = tempMap98.Get("x")
smallestXmap99 = tempObject                ' Here assign the Object, not the Map
End If
Next
Log(\$"Smallest x value is \${smallestX99}"\$)
Log("The log entry below should show content of (0,1), but it does not. Why?")
Log(\$"Map containing smallest x value has following content: (\${smallestXmap99.Get("x")},\${smallestXmap99.Get("y")})"\$)``````

Thanks for being a sounding board. It's finally clear as a bell and makes perfect sense (and somehow I have the feeling I've seen this before).

BTW, an alternative to re-dimming temp6Map within the For x = 0 / Next loop above is to assign mapList.Get(x) to smallestXmap3 instead of temp6Map. Again, it makes sense now.

#### EnriqueGonzalez

##### Well-Known Member
Longtime User

Replies
8
Views
500
B4J Question For each list
Replies
8
Views
648
Replies
3
Views
370
Replies
7
Views
1K
Replies
22
Views
16K