Variable by reference documentation? (v6 BUG)

Hi,

Is it no longer possible to have a global variable update by reference in v7?

:global TestVar;
:if ($TestVar = nil) do={
	:set TestVar [:toarray ""];
	:set ($TestVar->"nbr1") [:toarray ""];
	:set ($TestVar->"nbr1"->"count") 0;
}

:local nbr1 ($TestVar->"nbr1");
:set ($nbr1->"count") (($nbr1->"count") + 1);
:put ($nbr1->"count"); #1

On v6 the global variable is updated as “count” increments, but in v7 it does not.

Is there any documentation on what has changed v6 vs. v7 when it comes to scripting? e.g. did the model shift to COW?

Works for me on v7 too.

Depends on how you are trying to run that code, if you paste it in the terminal then whole code must be in {} braces otherwise local varaible expires in next line.

Hi Mrz,

Lets make sure its apples to apples:

/system script
add name=script1 policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=":global TestVar;\r\
    \n:if (\$TestVar = nil) do={\r\
    \n\t:set TestVar [:toarray \"\"];\r\
    \n\t:set (\$TestVar->\"nbr1\") [:toarray \"\"];\r\
    \n\t:set (\$TestVar->\"nbr1\"->\"count\") 0;\r\
    \n}\r\
    \n\r\
    \n:local nbr1 (\$TestVar->\"nbr1\");\r\
    \n:set (\$nbr1->\"count\") ((\$nbr1->\"count\") + 1);\r\
    \n:put (\$nbr1->\"count\"); #1\r\
    \n\r\
    \n:put (\$TestVar->\"nbr1\"->\"count\"); #0 on v7"

V6 output:

[admin@ros-v6-49-2] > /system script run script1
4
4
[admin@ros-v6-49-2] > /system script run script1
5
5
[admin@ros-v6-49-2] > /system script run script1
6
6

V7 output:

[admin@ros-v7-4] > /system script run script1
1
0
[admin@ros-v7-4] > /system script run script1
1
0
[admin@ros-v7-4] > /system script run script1
1
0

“if ($TestVar = nil) do={” NIL???
[@] > :global kkk
[@] > :put $kkk

[@] > :put [:typeof $kkk]
nothing
[@] > :global kkk
[@] > :put $kkk

[@] > :put [:typeof $kkk]
nothing
Correct:

:if ([:typeof $TestVar] = "nothing") do={

@merlinthemagic7, next time specify that the problem is when you reiterate the function, not on running it one time only…

The correct behavior is on v7, the local (=discarded later) variables must not be treated as pointer, and updating local variable must not influence global variable, until is not directly wanted.

a simplified examples work identically on both v6 and v7

{
:global TestVar
:if ([:typeof $TestVar] = "nothing") do={ :set TestVar 0 }
:local nbr1 $TestVar
:set $nbr1 ($nbr1 + 1)
:put $nbr1
}

Both work.

Can someone share a code snippet where a global array is set, then an index from that array is set in a local and when the index is changed the global reflects this change.

/system/script/environment/remove [find where name="TestVar"];

:global TestVar;
:if ($TestVar = nil) do={
	:put ("NIL works");
} else={
	:put ("NIL no workie");
}

:if ([:typeof $TestVar] = "nothing") do={
	:put ("Type 'nothing' works");
} else={
	:put ("Type 'nothing' no workie");
}

Shared memory is nice, as long as there the proper locks in place.

Is there a document i can read that informs of the change away from pointers? Would be nice to know what changes have been made between V6 and V7, before settling on a design pattern?

“nil” do not exist, like “str”

you can replace nil with any unexistant string and is the same

This works because is the returned string value of the typeof check

:if ([:typeof $TestVar] = "nothing") do={

test:

:put nil
:put anything
:put [:typeof [nothing]]
:put [:typeof [nil]]
:put [:typeof nothing]
:put [:typeof nil]

What happened on the past with nested array is a bug. If is a feature, also this must on v6 increase the TestVar value, but not happen…

{
:global TestVar
:if ([:typeof $TestVar] = "nothing") do={ :set TestVar 0 }
:local nbr1 $TestVar ; # nbr1 is not a pointer, the value is copied
:set $nbr1 ($nbr1 + 1)
:put $nbr1
:put $TestVar ; # the global var is not influenced
}

using your example, just removing one nested array, also this, if is a feature, must update main TestVar, but is not happening on v6 or on v7

{
:global TestVar;
:if ($TestVar = nil) do={
	:set TestVar [:toarray ""];
	:set ($TestVar->"count") 0;
}

:local nbr1 ($TestVar->"count"); # this is not one pointer, the value inside the array is copied
:set $nbr1 ($nbr1 + 1);
:put $nbr1
:put $TestVar ; # this remaining not influenced
}

This is the BUG on v6 and on v7 is fixed.

{
:global TestVar;
:if ($TestVar = nil) do={
	:set TestVar [:toarray ""];
	:set ($TestVar->"nbr1") [:toarray ""];
	:set ($TestVar->"nbr1"->"count") 0;
}

:local nbr1 ($TestVar->"nbr1"); # BUG on v6, instead of copy inner array, is copied the memory position
:set ($nbr1->"count") (($nbr1->"count") + 1);
:put ($nbr1->"count");
:put $TestVar; # is influenced because the presence of the BUG.
}

I believe you. Is there any document that talks about this and other changes? Where did you learn that MT considers this a bug to be fixed in V7? Like the title says, im looking for documentation.

There is no need to see it written when it clearly works only in extreme cases and in normality it does not happen…
I repeat: if it was intended, the behavior should have been the same in the other examples,
AND ESPECIALLY there had to be a method to copy WITHOUT necessarily creating a reference that update global variable…


“change” are listed when something is done on purpose
when a bug is fixed, can be “accidentally” fixed because is not known…

for more information contact directly support@mikrotik.com and hope than some programmers reply about this bug…

There is no documentation about variable referencing because RouterOS scripting does not have referencing concept. Set should perform deep copy which it apparently did not in ROSv6.