Jump to content

Global dynamic variable inside function - (Moved)


Go to solution Solved by TheXman,

Recommended Posts

Hello everyone,

It helped me a lot with all the messages in the forum, the truth is that it is a community that has many resources and I have never had to ask a question until now since I cannot find any answer on the web.

the question is that i need to declare global dynamic variables inside a function

I leave you my example code:
 

Func InitialSetupFile()
    $SetupFile = ReadSetupFile()
    ;~ Declare all global variables from config File
    Local $oJson = Json_Decode($JSON_setup)
    Local $SETOPJSON = Json_Get($oJson, '.setup')
    For $i = 0 To UBound($SETOPJSON) - 1 Step 1
        Local $SETOPJSON2 = Json_Get($oJson, '.setup[' & $i & '].values')
        For $j = 0 To UBound($SETOPJSON2) - 1 Step 1
            Local $iniGroup = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniGroup')
            Local $iniProp = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniProp')
            Local $defaultValue = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].defaultValue')
            $dynamicVariableName = "Setup_" & $iniGroup & "_" & $iniProp
            Global $dynamicVariableName
            Assign($dynamicVariableName, $SetupFile[$i][$j][3])
        Next
    Next
EndFunc

InitialSetupFile()

I will explain the code

1. read a file with values and return them in an array inside $SetupFile

2. I loop through a variable in json format ($JSON_setup) to extract the values I need to create my global variables

3. use the extracted values to create global variable $$dynamicVariableName and assign the extracted value from the configuration file

***

The thing is that if I run this code in the root of the script, that is, I run it outside the InitialSetupFile() function, everything works as I expect, but if I run it inside the function, I can't access any global dynamic variable later.

Does anyone know what may be going on and can provide me with a solution to make this work?

Thank you very much (By google translator)

Link to comment
Share on other sites

  • Developers

Moved to the appropriate AutoIt General Help and Support forum, as the Developer General Discussion forum very clearly states:

Quote

General development and scripting discussions.


Do not create AutoIt-related topics here, use the AutoIt General Help and Support or AutoIt Technical Discussion forums.

Moderation Team

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

First, it's best if you understand how scope works, so I recommend that you read this page: https://www.autoitscript.com/wiki/Variables_-_using_Global,_Local,_Static_and_ByRef

Second, since AutoIt parses/executes line by line, if you try to access your $dynamicVariableName before the function has run, it does NOT exist. Instead, you should do something like this:

; Declare variables first/at the top of your script. This way they're initialized and you won't try to access them before they exist
Global $dynamicVariableName

InitialSetupFile()

; Generally in AutoIt functions are put at the bottom of the script. Functions are loaded when the script starts, so they don't need to appear before they're used
Func InitialSetupFile()
    ; Declare your variables first
    ; It's not a good idea to do delcaration (Local) inside of loops, since you're re-creating the variable each loop
    Local $defaultValue
    Local $iniGroup, $iniProp
    Local $SETOPJSON, $SETOPJSON2
    Local $SetupFile = ReadSetupFile() ; You should always declare new variables with the correct scope
;~ Declare all global variables from config File
    Local $oJson = Json_Decode($JSON_setup)
    $SETOPJSON = Json_Get($oJson, '.setup')

    For $i = 0 To UBound($SETOPJSON) - 1 Step 1
        $SETOPJSON2 = Json_Get($oJson, '.setup[' & $i & '].values')
        For $j = 0 To UBound($SETOPJSON2) - 1 Step 1
            $iniGroup = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniGroup')
            $iniProp = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniProp')
            $defaultValue = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].defaultValue')
            $dynamicVariableName = $SetupFile[$i][$j][3] ; Update the Global variable. Since it's global, it is accessible here
            ; I'm not sure what value you want for $dynamicVariableName, either ("Setup_" & $iniGroup & "_" & $iniProp) or ($SetupFile[$i][$j][3])
            ;$dynamicVariableName = "Setup_" & $iniGroup & "_" & $iniProp
            ;Global $dynamicVariableName
            ;Assign($dynamicVariableName, $SetupFile[$i][$j][3])
        Next
    Next
EndFunc   ;==>InitialSetupFile

Variables that are not inside functions are in the Global scope, and are accessible inside of functions. However if you declare a Global variable in a function, that variable does NOT exist until that function runs. Also note that you can use a Local variable by the same name as a Global variable in a function, and while in the function you'll use the Local version (however it does NOT inherit or use the global scopes value, unless you set it to that).

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

Thanks for the reply @mistersquirrle

I already read the link https://www.autoitscript.com/wiki/Variables_-_using_Global,_Local,_Static_and_ByRef

TI'll try your proposal tomorrow, but logic tells me that when I put at the top of my script this:

 

Global $dynamicVariableName

 

I'm actually globally declaring the variable $dynamicVariableName, Not the dynamic variable I want to create:

 

"Setup_" & $iniGroup & "_" & $iniProp (example: $Setup_Main_Path)

 

I am right?

Link to comment
Share on other sites

I think I see now what you're looking to do, you're trying to create a new variable with a dynamic name that's stored in $dynamicVariableName and is: "Setup_" & $iniGroup & "_" & $iniProp. So you're trying to dynamically create the variable $Setup_Main_Path, and you may not know what name you want when you create the script.

Honestly this is not something that I do, I usually know what variables I want beforehand. But let me ask this, then, once you've created the global variable $Setup_Main_Path, then what? How are you going to access it, if you don't know the name? With Eval each time? Eval($dynamicVariableName). My question then is... why? Why not just create a variable (array or map maybe) to hold the data that you know the name of?

I would recommend checking out Maps in the latest version of AutoIt. They have been added to the stable release: https://www.autoitscript.com/autoit3/docs/intro/lang_variables.htm#ArrayMaps

 

This way, you can instead do something like this:

; Declare variables first/at the top of your script. This way they're initialized and you won't try to access them before they exist
Global $mDynamicVars[] ; [] - create a Map when you don't set a size or any values (otherwise it will create an array)

InitialSetupFile()

ConsoleWrite($mDynamicVars["Setup_Main_Path"] & @CRLF)

; Generally in AutoIt functions are put at the bottom of the script. Functions are loaded when the script starts, so they don't need to appear before they're used
Func InitialSetupFile()
    ; Declare your variables first
    ; It's not a good idea to do delcaration (Local) inside of loops, since you're re-creating the variable each loop
    Local $defaultValue
    Local $iniGroup, $iniProp
    Local $SETOPJSON, $SETOPJSON2
    Local $SetupFile = ReadSetupFile() ; You should always declare new variables with the correct scope
;~ Declare all global variables from config File
    Local $oJson = Json_Decode($JSON_setup)
    $SETOPJSON = Json_Get($oJson, '.setup')

    For $i = 0 To UBound($SETOPJSON) - 1 Step 1
        $SETOPJSON2 = Json_Get($oJson, '.setup[' & $i & '].values')
        For $j = 0 To UBound($SETOPJSON2) - 1 Step 1
            $iniGroup = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniGroup')
            $iniProp = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniProp')
            $defaultValue = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].defaultValue')
            ; Create a new map key
            $mDynamicVars["Setup_" & $iniGroup & "_" & $iniProp] = $SetupFile[$i][$j][3]
        Next
    Next
EndFunc   ;==>InitialSetupFile

 

Edited by mistersquirrle

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

  • Solution
1 hour ago, ALarvi019 said:

the question is that i need to declare global dynamic variables inside a function

If you must, you can do it using the Assign() function and you can read the dynamically created global variable with the Eval() function.

 

Example:

#include <Constants.au3>

Const $IniGroup = "Main", _
      $IniProp  = "Path"

example()
ConsoleWrite("Setup_" & $IniGroup & "_" & $IniProp & " = " & Eval("Setup_" & $IniGroup & "_" & $IniProp) & @CRLF)

Func example()
    ;Create and assign a value to a dynamically created variable name
    Assign("Setup_" & $IniGroup & "_" & $IniProp, "Some Value", $ASSIGN_FORCEGLOBAL)
EndFunc

Console:

Setup_Main_Path = Some Value

 

Link to comment
Share on other sites

31 minutes ago, mistersquirrle said:

I think I see now what you're looking to do, you're trying to create a new variable with a dynamic name that's stored in $dynamicVariableName and is: "Setup_" & $iniGroup & "_" & $iniProp. So you're trying to dynamically create the variable $Setup_Main_Path, and you may not know what name you want when you create the script.

Honestly this is not something that I do, I usually know what variables I want beforehand. But let me ask this, then, once you've created the global variable $Setup_Main_Path, then what? How are you going to access it, if you don't know the name? With Eval each time? Eval($dynamicVariableName). My question then is... why? Why not just create a variable (array or map maybe) to hold the data that you know the name of?

I would recommend checking out Maps in the latest version of AutoIt. They have been added to the stable release: https://www.autoitscript.com/autoit3/docs/intro/lang_variables.htm#ArrayMaps

 

This way, you can instead do something like this:

; Declare variables first/at the top of your script. This way they're initialized and you won't try to access them before they exist
Global $mDynamicVars[] ; [] - create a Map when you don't set a size or any values (otherwise it will create an array)

InitialSetupFile()

ConsoleWrite($mDynamicVars["Setup_Main_Path"] & @CRLF)

; Generally in AutoIt functions are put at the bottom of the script. Functions are loaded when the script starts, so they don't need to appear before they're used
Func InitialSetupFile()
    ; Declare your variables first
    ; It's not a good idea to do delcaration (Local) inside of loops, since you're re-creating the variable each loop
    Local $defaultValue
    Local $iniGroup, $iniProp
    Local $SETOPJSON, $SETOPJSON2
    Local $SetupFile = ReadSetupFile() ; You should always declare new variables with the correct scope
;~ Declare all global variables from config File
    Local $oJson = Json_Decode($JSON_setup)
    $SETOPJSON = Json_Get($oJson, '.setup')

    For $i = 0 To UBound($SETOPJSON) - 1 Step 1
        $SETOPJSON2 = Json_Get($oJson, '.setup[' & $i & '].values')
        For $j = 0 To UBound($SETOPJSON2) - 1 Step 1
            $iniGroup = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniGroup')
            $iniProp = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].iniProp')
            $defaultValue = Json_Get($oJson, '.setup[' & $i & '].values[' & $j & '].defaultValue')
            ; Create a new map key
            $mDynamicVars["Setup_" & $iniGroup & "_" & $iniProp] = $SetupFile[$i][$j][3]
        Next
    Next
EndFunc   ;==>InitialSetupFile

 

I like this idea!!! How can I access the value?

MsgBox...... $mDynamicVars["Setup_Main_Path"] 

thanks 

Link to comment
Share on other sites

What do you mean how can you access it? You just did, basically. I also have it being used in ConsoleWrite in the example. 

It's accessed like: 

MsgBox(0, 'Setup_Main_Path', $mDynamicVars["Setup_Main_Path"])

Or, you can do this to get all of the keys and values for that key:

Global $mDynamicVars[]

$mDynamicVars["Setup_Main_Path"] = 'Setup_Main_Path'
$mDynamicVars["Meow"] = 'Cat'
$mDynamicVars["Woof"] = 'Dog'

Global $aKeys = MapKeys($mDynamicVars)
For $sKey In $aKeys
    ConsoleWrite($sKey & ': ' & $mDynamicVars[$sKey] & @CRLF)
Next

 

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

hello all

@mistersquirrle Although your idea of using maps is very cool and interesting, I would have to change many parts of my code to make it work. Thank you very much for your help and time.

 

@TheXman 

Thank you very much for the answer, your solution is perfect for me.  $ASSIGN_FORCEGLOBAL

  Assign("Setup_" & $IniGroup & "_" & $IniProp, "Some Value", $ASSIGN_FORCEGLOBAL)

I can access dynamic variables outside of functions just fine. It was what I needed!!!

Problem solved!!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...