Passing variables to functions

Functions provide a great way to repeat commands and eliminate duplicate code. I found a forum thread about the topic, yet I am unable to figure out how to pass variables to a function. A simple test script:

:global DisplayMessages do={
   :put "$Msg";
   :log info "$Msg"
}

:local TestVariable "passing a variable to a function."

DisplayMessages Msg="This is a test of $TestVariable."

/system script environment remove DisplayMessages

The script fails to execute.

Changing :local TestVariable to :global TestVariable fails.

The referenced thread indicates I should use global variables and somehow “parse” information into the global environment. At that point I am lost.

How do I pass variables to a function?

Thank you. :slight_smile:

Did you have a look at this post?
http://forum.mikrotik.com/t/functions-and-function-parameters/68159/1

Did you have a look at this post?

Yes, that is the script I linked to in my original post.

Everything is clear as mud to me. :slight_smile:

Simple MyFunc with only arguments
Create in /system script a script1 with code:

# #################### Function 1 Start, Main program below ##################
/local MyFunc do={
/put "Some code inside function";
/put "I can display arguments send to this function as: "
put ("  \$0 is your function name       : ".$0);
put ("  \$1 is 1st arg you provide      : ".$1);
put ("  \$2 ...                         : ".$2);
put ("  \$3 empty if you not provide it : ".$3);
put ("  \$NameOfArg                     : ".$NameOfArg);
put "End of Function";
};
# ################# Main Program ########################
# Run MyFunc with args
$MyFunc "parameter1" "some_arguments" NameOfArg="ThisIsValueOfSpecialArgumentsWithHisOwnName";

and run it from “New Terminal” by

/system script run script1

and output is:

Some code inside function
I can display arguments send to this function as: 
  $0 is your function name       : $MyFunc
  $1 is 1st arg you provide      : parameter1
  $2 ...                         : some_arguments
  $3 empty if you not provide it : 
  $NameOfArg                     : ThisIsValueOfSpecialArgumentsWithHisOwnName
End of Function

This is simple use of Function to use your code many times in “MAIN part of script”.

Script with :return and executive/run it via put command
Create system script and run it from terminal, code:

/local VarWorksInScriptWithoutInternalsFunction "Some exist data in text";
put ("\$VarWorksInScriptWithoutInternalsFunction value is: ".$VarWorksInScriptWithoutInternalsFunction);

# #################### Function 1 Start, Main program below ##################
/local MyFunc do={
/put "MyFunc start..."
put ("\$VarWorksInScriptWithoutInternalsFunction value is: ".$VarWorksInScriptWithoutInternalsFunction);
/local VarWorksOnlyInsideFunction "23:10:15";
# Change this var by adding 1minute and 10 second to this time entry.
/set $VarWorksOnlyInsideFunction ($VarWorksOnlyInsideFunction +1m10s);
/put ("\$VarWorksOnlyInsideFunction is now; ".$VarWorksOnlyInsideFunction);
/put "MyFunc stop...";
/return $VarWorksOnlyInsideFunction;
};

# ################# Main Program ########################

# Run MyFunc
/put ("Main Program with returned value from MyFunc is: ".[$MyFunc "This is not used 1 argument inside MyFunc"]);

Output:

$VarWorksInScriptWithoutInternalsFunction value is: Some exist data in text
MyFunc start...
$VarWorksInScriptWithoutInternalsFunction value is: 
$VarWorksOnlyInsideFunction is now; 23:11:25
MyFunc stop...
Main Program with returned value from MyFunc is: 23:11:25

I hope this way you can understand how to use the Functions with parameters. Please test all info from WIKI and now you can understand it.

Final solution:

local DisplayMessages do={
   :put "$msg";
   :log info "$msg"
}
:local TestVariable "passing a variable to a function."
$DisplayMessages msg=("This is a test of ".$TestVariable);
local DisplayMessages do={
   :put "$msg";
   :log info "$msg"
}
:local TestVariable "passing a variable to a function."
$DisplayMessages msg=("This is a test of ".$TestVariable);

Thank you! :smiley:

I did not know functions could be local. The above referenced thread did not mention that or I just failed to understand.

Also I needed the parentheses and that oddball “dot” before the variable.

What a difficult scripting language. :frowning:

Just search the WIKI, read few times the most important article and try practice it.
Main gold is: https://wiki.mikrotik.com/wiki/Manual:Scripting

/local with function not work in first place, in ROS with first version of function, this was fixed in later version and it’s why you not read post with a local example.
At WIKI example’s are complicated. I must do some own this two examples to found how to use it on easy function like Turbo Pascal programming :).

Ones more information for education about this topic.

Quiz: Why global variable $c from inside MyFunc without “:return $c ;” still exist ?
.
Screenshot_2.jpg
.
Answer hide here, just select text from here >>
Just because it is :global and it must be save in “/system script environment” !
Means it’s not bug, it’s :global feature !
<< to here.

Source code from screenshot:

system script environment print where name=c;
system script environment remove [find name=c];
system script environment print where name=c;
{
delay 1s; beep;
local a "localA"; put $a;
put "***** enter function *****"
local MyFunc do={set $a "changedA"; put $a; local b "localB"; put $b; global c "globalC"; put $c;system script environment print where name=c;}
put "***** exit function *****"
put "\$a: $a";
put ("\$b: ".$b);
put $"c";
put "***** Run Function: *****"
$MyFunc
put "***** After Function: *****"
put "\$a: $a";
put ("\$b: ".$b);
put $c;
}
system script environment print where name=c;
system script environment remove [find name=c];
system script environment print where name=c;

.
.
And some Fact’s about Function

Situation 1) Just created local/global not work in function
*) If you create a new global or local in script then you cannot use it in Funcrion inside. The global will be created after that you :quit script.
*) Function can use with global who exist in ROS env befor startung your script. Means your script with new global works on second and next runnings. Be aweare that.
.

{ global GlobalVar "SomeValue"
local MyFunc do={put $GlobalVar}
$MyFunc }

.

{ local LocalVar "SomeValue"
local MyFunc do={put $LocalVar}
$MyFunc }

.
Situation 2) Passing arguments to Funcrion
*) New local and global created inside script who was pass to Funcrion as arguments can be used inside, but all modify will be only inside Function itself.
*) global created in ROS env before running script can be access and modify inside Funcrion. Means second and next runnings will be works with global.

{ global GlobalVar "SomeValue"
local MyFunc do={put $1}
$MyFunc $GlobalVar }

.
Situation 3) Receive feedback from Function
*) return can give feedback as only one value from Funcrion. This value can be array with multiple data in it.
*) globals who exit before script start will works correctly

{ local LocalVar "SomeValue"
local MyFunc do={return ($1."AfterChange")}
local FeedBack [$MyFunc $LocalVar]
put $FeedBack }

.
Situation 4) Check if result from :return is not “;” char, it is array..
*) When we not specify what value be :return then by default we receive the “;” chars as function feedback. This is array with :len >=2.
.
Problem is perfect specify this

{ local LocalVar "SpecificValue"
local MyFunc do={ if ($1="SpecificValue") do={return ($1."AfterChange")}}
for i from=1 to=4 do={ set $LocalVar [$MyFunc $LocalVar] ; put $LocalVar } }

Output will be: SpecificValueAfterChange > ; > ; > ;
.
Else={return “”} | Else={return $1} | Else={return [nothing]} as solve
.

{ local LocalVar "SpecificValue"
local MyFunc do={ if ($1="SpecificValue") do={return ($1."AfterChange")} else={return [nothing] }}
for i from=1 to=4 do={ set $LocalVar [$MyFunc $LocalVar] ; put $LocalVar } }

Output will be: SpecificValueAfterChange > “” > “” > “”
.
or just check is feedback it’s not array;
.

{ local LocalVar "SpecificValue"
local MyFunc do={ if ($1="SpecificValue") do={return ($1."AfterChange")}}
for i from=1 to=4 do={ set $LocalVar [$MyFunc $LocalVar] ; if ([typeof $LocalVar]!="array") do={put $LocalVar}}}

.
Output will be: SpecificValueAfterChange