Page 1 of 1

Map access questions

Posted: Sat Feb 03, 2024 7:19 pm
by dougmo52usr
I see in the help, that I can pass a Map ByRef like Procedure DebugMap(Map ParameterMap.s()).

Suppose I rather need to pick a map within a function at runtime. The code below which obviously fails compile, gives an idea of what I want to accomplish. Is there a way to create a local variable and initialize it to a map reference?

Code: Select all

Enumeration MapID
  #MapOfStringsA = 1
  #MapOfStringsB
  #MapOfStringsC
EndEnumeration

Global NewMap MapOfStringsA.s()
Global NewMap MapOfStringsB.s()
Global NewMap MapOfStringsC.s()

Procedure GetMapRef(Map MapOfStrings.s())
  ProcedureReturn @MapOfStrings()
EndProcedure

Procedure InitMap(MapID)
  Protected *MapOfStrings, i=0
  Select MapId
    Case #MapOfStringsA
      *MapOfStrings = GetMapRef(MapOfStringsA())
    Case #MapOfStringsB
      *MapOfStrings = GetMapRef(MapOfStringsB())
    Case #MapOfStringsC
      *MapOfStrings = GetMapRef(MapOfStringsC())
  EndSelect
  ForEach *MapOfStrings
    i = i + 1
    AddMapElement(*MapOfStrings(),"Key"+Str(i)
    *MapOfStrings() = i
  Next
  ForEach *MapOfStrings()
    Debug MapKey(*MapOfStrings())
  Next
EndProcedure

Procedure main()
  InitMap(#MapOfStringsA)
EndProcedure

main()

Re: Map access questions

Posted: Sat Feb 03, 2024 9:06 pm
by infratec
What you are doing is not possible.

*MapOfStrings is only a pointer to the current map element and not a map pointer.

And even if it would work ...

Code: Select all

 
 ForEach *MapOfStrings
    i = i + 1
    AddMapElement(*MapOfStrings(),"Key"+Str(i)
    *MapOfStrings() = i
  Next
Inside the loop you add an element, so the loop maybe endless
And you assign an integer to a string map.

And, I don't fully understand what you want.
Ok, you want to have access to different maps in one procedure.
But what you want to do inside of the for loop?

Re: Map access questions

Posted: Sat Feb 03, 2024 9:25 pm
by infratec
Maybe something like this:

Code: Select all

EnableExplicit

Enumeration MapID
  #MapOfStringsA
  #MapOfStringsB
  #MapOfStringsC
EndEnumeration


Structure TestMap_Structure
  Map MapOfStrings.s()
EndStructure

Structure Test_Structure
  List MapList.TestMap_Structure()
EndStructure

Global Test.Test_Structure

Procedure GetMapRef(Map MapOfStrings.s())
  ProcedureReturn @MapOfStrings()
EndProcedure

Procedure InitMap(MapID)
  Protected *MapOfStrings, i.i
  
  SelectElement(Test\MapList(), MapId)
  
  For i = 0 To 2
    AddMapElement(Test\MapList()\MapOfStrings(), "Key"+Str(i))
    Test\MapList()\MapOfStrings() = Str(i)
  Next i
  
  ForEach Test\MapList()\MapOfStrings()
    Debug MapKey(Test\MapList()\MapOfStrings())
  Next
EndProcedure


Procedure main()
  InitMap(#MapOfStringsA)
EndProcedure


AddElement(Test\MapList())
AddElement(Test\MapList())
AddElement(Test\MapList())

main()

Re: Map access questions

Posted: Mon Feb 05, 2024 12:52 am
by dougmo52usr
Your method certainly works. I was hoping that I could avoid passing a map in a structure by creating a map reference.

In DoSomething1, Global MapA is altered through a reference. In DoSomething2, Global MapA is altered directly. In the Procedures, MapA syntax looks exactly the same.

Is there a way to create a DoSomething3 with a local variable that references a map similar to how DoSomething1 did when it passed MapA? I was hoping that @MapA() would give the MapA address, but it apparently gives the address of the current element. On the other hand, DoSomething1(Map MapA.s()) gets the MapA address.

Code: Select all

; create a global map
Global NewMap MapA.s()

; access a global map by reference 
Procedure DoSomething1(Map MapA.s()) 
  ; add an element to a global map
  AddMapElement(MapA(),"Key1")
  ; set it's value
  MapA() = "Value1"
EndProcedure

; access a global map directly
Procedure DoSomething2()
  ; add an element to a global map
  AddMapElement(MapA(),"Key1")
  ; set it's value
  MapA() = "Value1"
EndProcedure

Procedure DoSomething3()
  Protected RefToMapA = ????
  ; add an element to a global map
  AddMapElement(RefToMapA(),"Key1")
  ; set it's value
  RefToMapA() = "Value1"  
EndProcedure