Strange array index behavior

Hi all, could you please help confirm whether this is expected behavior or a bug? Thank you.

:local testarr [:toarray ""]
:set ($testarr->"2") "str 2"
:set ($testarr->2) "int 2"
:local testIdx 2

:log warn ($testarr->"2")     #output: str 2
:log warn ($testarr->"$testIdx")  #output: int 2   ->     i think it should be str 2
:set testIdx [:tostr $testIdx]
:log warn ($testarr->"$testIdx")  #output: str 2

ros version: 7.15.3

2 as number is not the same as “2” as string.

Is not a bug on RouterOS, you must understand the differencies between one string and one number.

“$testIdx” is a redundancy for $testIdx only without quotes, so all “$testIdx” is converted with $testIdx value, 2 as number.
using :tostr you force convert $testIdx before is used as variable.

What happens with?:

:set testIdx [:tostr $testIdx]
:log warn ($testarr->$testIdx)

for sure:

output: str 2



This is just an example, but it is a feature that is never kept in mind to call variables with meaningful and non-misunderstanding names…

No, it isn't.

OP has double quotes around $testIdx in the second line:

:set testIdx [:tostr $testIdx]
:log warn ($testarr->> "> $testIdx> "> ) #output: str 2

The question is what happens once the 2 is transformed into a string and assigned to the array WITHOUT double quotes.

In other words a 2 as string is a string with or without quotes, 2 as a number may become a string when surrounded by quotes, but it may also remain a number, notwithstanding the quotes.

See previous reply :wink:

For example, 1 can be 1 as a number, “1” as a string and… 1 as true… 1 as array, 1 as time… etc. etc. etc.
It all depends on the context and how badly the script was written
:if (1) do={:put “true”} ; # NOTE: is not like (1 = true)…

true

:local x 1 ; :put [:typeof $x]

num

:local x “1” ; :put [:typeof $x]

str

:local x [:toarray 1] ; :put [:typeof $x] ; put $x

array

1

:local x [:totime 1] ; :put [:typeof $x]

time

The ambiguity (I believe present in other computer languages/scripting) is in the quotes behaviour.

When doing:

:set ($testarr->2)

2 is a value read by the parser as number, or to be even more strict, 2 is an unknown type value and the parser attributes to it a number type.

When doing:

:set ($testarr->"2")

2 is still the same as above (unknown type), but since it is enclosed in double quotes the parser attributes to it a string type.

When doing:

:local testIdx 2

the variable testidx value is set as 2 AND the type is set as number

When doing:

:log warn ($testarr->"$testIdx")

the double quotes are NOT “used” anymore by the parser because the type is ALREADY set as number, so it is perfectly equivalent to:

:log warn ($testarr->$testIdx)

That’s exactly what I meant, thank you.