Functions and function parameters

Starting from v6.2 we have added new syntax which allows to define functions and even pass parameters to them
:global myFunc do={
:put “arg a=$a”;
:put “arg ‘1’=$1”
}
$myFunc a=“this is arga value” "this is arg1 value"Output:

arg a=this is arga value
arg '1'=this is arg1 value

Read more in documentation:
http://wiki.mikrotik.com/wiki/Manual:Scripting#Functions

I just want to say one thing: I LOVE YOU!

This is something that will make my daily work so much easier :slight_smile:

Nice! :sunglasses:

Just one question… if I have a script in script environment, must I “:parse” it into a variable before I’m able to call it with parameters, or does this syntax apply to the run command as well? i.e. could I do something like
/system script run myScript myVar=myValueAnd analogously for “/import” scripts?

You can’t pass variables with run command. You will need to parse script into variable as shown in the examples.

OK, but… Could we hopefully get that in the (near?) future?

Few more features:

  • Now function can return value with :return command
  • Catch run-time errors
    :do {
    :put [:resolve test.com];
    } on-error={ :put “resolver failed”};
    :put “lala”
output:
resolver failed
lala

http://wiki.mikrotik.com/wiki/Manual:Scripting#Catch_run-time_errors

Keep it up, thats some great additions.

Similarly to the question before… can one :return from a script/import?

(Yeah, I really prefer abstracting away utility functions away, for re-usability’s sake)

Currently no, but as a workaround you can add scheduler to run on startup script which will import all required scripts into :global variables.

I got time today to play with this, so a few questions:

  1. It seems you cant pass variables to functions, this should work, but doesnt:
    :global PutValue do={
    :put $1
    }

:for i from=1 to=3 do={
:put $i
$PutValue $i
}2) Can you not define functions as :local? This should work, but doesnt:
{
:local PutString do={
:put function
}

:for i from=1 to=3 do={
:put $i
$PutString
}
}

Finally something to improve the scripting, but do you plan to implement JIT compilation of the scripts or some other means to lower the CPU utilization as well? It is needed because the scripting engine on ROS is killing the system performance - it is too simple to implement a script that is doing nothing, but CPU load is at 100%.

tomaskir these problems will be fixed in next release.

Thanks!

Another thing which doesnt work is functions accessing local variables:
{
:local sText “This is a sting of text.”

:global putString do={
:put $sText
}

$putString
:put $sText
}So since I cant at the moment define local functions yet, I have to keep all my variables and all my functions as global, which is a mess and creates potential for naming conflicts :slight_smile:

Of course it will not work, function is function and it can’t see local variables defined in main scope.

You need to pass parameter when executing function

for example:
:global sText “This is a sting of text.”
:global putString do={
:put $txt
}
$putString txt=$sTextSince there is a bug with local vars being passed. I am using global as an example

You mentioned that you will fix functions to work in local scope in next release. So theoretically:

Since the whole script is enclosed in { }, the whole script is a single scope.
:local functions defined in this scope should be able to access other :local variables defined in the same scope.

So will it be possible (in next release when :local functions work) to do this, since the function and variable are in same scope?
{

local variable

:local sText “This is a sting of text.”

local function

:local putString do={
:put $sText
:set sText “Now a different string of text”
}

$putString
:put $sText
}As you said, you can acomplish this with passing an argument to the function, but if it also works this way, it gives us more options :slight_smile:
I dont have to pass an argument and then return a value, all is handled with the variable, so less code to accomplish the same.


Also, one more request, since it seems you guys are actively working in this area right now. Would it be possible to implement a “date” variable type? We have a “time” type which works great. Example:
{
:local curTime
:local curDate

:set curTime [/sys clock get time]
:put [:typeof $curTime]

works great with compares etc

:if ($curTime > “12:00:00”) do={
:put “Its after noon”
} else={
:put “Its before noon”
}

also works great

:put ($curTime + 1h)

:set curDate [/sys clock get date]
:put [:typeof $curDate]

doesnt work since type is str

:if ($curDate > “jan/01/2013”) do={
:put “We are after 2013”
} else={
:put “We are before 2013”
}

doesnt work since type is str

:put ($curDate + 1d)
}If a “date” type existed and was handled the same way as a “time” type, it would save me SO MUCH work in scripting. It would only take a couple of hours for a programmer to make this, but would save hundreds :slight_smile:

Also thanks to listening to my silly requests :slight_smile:

As you said, you can acomplish this with passing an argument to the function, but if it also works this way, it gives us more options > :slight_smile:
I dont have to pass an argument and then return a value, all is handled with the variable, so less code to accomplish the same.

You will never be able to access local variables (defined outside function) inside function. For that use global variables.

Understood, will either pass argument and return value, or use a :global.

Any info on the “date” type?

Do you have an example of using the :return feature? I cannot find an example of it on the Wiki.

Return example added:
http://wiki.mikrotik.com/wiki/Manual:Scripting#Functions