is there any associative array, hash, map?

is there any associative array, hash, map?

The change log for 6.2 implies that there is in that version with the statement:

*) console - array value syntax in expressions ‘{1;2;3;4}’ now can
specify values with word keys as ‘{a=1;b=2}’;

but I don’t really see it working as you’d expect, i.e.
:pick $assoc "a"will NOT give you the element with a key called “a”, and there isn’t a different command that would. What’s more puzzling is that
:pick $assoc 0will not give you just the value, but also the “a=” prefix… in other words, it’s EXACTLY as if associative arrays are not supported at all, and you’re getting a plain ol’ string.

I guess what the change is ACTUALLY saying is that is no longer considered a syntax error (but is instead interpreted as a plain string), whereas it previously would be.

With all that said - apparently no. There are no associative arrays in scripting (yet?).

I wrote two helper functions to store values in environment as global vars.
but there is bug - you can pass variables to functions.
Waiting for 6.3…
:global setHashValue do={
:global hashSetter [:parse “:global $1$2 $3”];
$hashSetter;
}

:global getHashValue do={
:global hashLastValue nil;
:global hashGetter [:parse “:global $1$2 ; :global hashLastValue $$1$2” ];
$hashGetter;
:return $hashLastValue;
}

$setHashValue “myHash” “keyA” 123;
$setHashValue “myHash” “keyB” 456;
$setHashValue “myHash” “keyC” 678;

:log info [$getHashValue “myHash” “keyA”];
:log info [$getHashValue “myHash” “keyB”];
:log info [$getHashValue “myHash” “keyC”];

I just saw this topic, which seems to suggest that there ARE associative arrays, and you can access a key with

$array->"key"

But then, I tried to define one from scripting, but never managed to match a key (an empty string was returned instead). I tried

:local assoc ({},"a"="test1")



:local assoc ({"a"="test1"})



:local assoc {"a"="test1"}

all with the same result.

Side note - that last syntax produces an array with two numeric members - value “a” at offset 0, and “test1” at offset 1.

(I’m using 6.4)

@MikroTik support
Is there anyway an associative array can be defined by a user (and then accessed using the above, or different, syntax), or is this currently just internally supported? If just internally at the moment - any plans to add it for users in the (near) future?

[admin@x86] > :global aaa {a=1;b=2;c=3}
[admin@x86] > :put ($aaa->“a”)
1
[admin@x86] > :put ($aaa->“b”)
2

Well… THAT seems to work. And I also tried time and Boolean values, and they work too.

In that case, it seems the problem is limited just to string values - they are always empty.

And also, the new “->” is not yet documented.

Could you post some example with strings that doesn’t work?

Just did in the last post:

:local assoc {"a"="test1"}
:put [($assoc->"a")]

If you replace

"test1"

with a number, a time or Boolean value, it works as expected, but this doesn’t, and unquoting the string doesn’t help either, i.e.

:local assoc {"a"=test1}
:put [($assoc->"a")]

also outputs an empty line.

All of these are from within a script in “/system script” that is then “run”-ed from a Winbox terminal window, with the router being an x86 machine (in case that’s relevant too).

Thanks it is a bug, creates array of both elements (see :environment print)

We will fix this.

How do you set just one element of such a hash?

:global assoc {a=1;b=2;c=3};

:put ($assoc->“a”)

1

:put ($assoc->“b”)

2

env pr

assoc={a=1; b=2; c=3}


now i want to change the value of b

:set assoc {b=5}

:put ($assoc->“b”)

5

but now when I look at the other rows, they are gone. the set has wiped out the other elements.

:put ($assoc->“a”)

env pr

assoc=whats the correct set syntax to change only one element of a hash? Thanks

Was there ever an answer to this? How do you set a single element in an array? or an associative array?

set overwrites value of variable, so in example you are setting array with one element
:set assoc {b=5}


Currently there is no command to change single element in array.

Ugh… ok. Helping someone out with a project and the basically non-existent data structures and lack of atomic operations are a problem. I can’t use pick and set since if the thread gets interrupted I will be hosed… some sort of semaphore/mutex or something along with push/pop and actual linked lists would be really useful.

We are planning to add commands to change individual array elements. Most likely in v6.7 you will have this feature.

What about atomic operations?.. right now if I have multiple threads attempting to access a single list (e.g. utilizing Traffic Monitors etc)… can I be guaranteed that the push/pop operations will not loose entries?

-Eric

Personally, I'd prefer named locks instead of some sort of atomic flavored operations.

e.g.
:lock "nameOfMyLock" do={

Stuff that must be atomic in relation to "nameOfMyLock".

i.e. any other code featuring a ":lock" with "nameOfMyLock" will block at that point until THIS section is exited.

:set "globalVariableCounter" ($globalVariableCounter + 1)

}Ideally, there should also be an option for shared locks and a timeout... but most scripts would be fine even with just exclusive indefinite locks.

Now setting value to single array element also works
[admin@MikroTik] > :global rr { “apple”=12345; “peach”=“abe” }
[admin@MikroTik] > :set ($rr->“apple”) “lala”
[admin@MikroTik] > :environment print
rr={apple=“lala”; peach=“abe”}

How about some sort of mutex/lock/semaphore?

hi, is there a way to assign values to a variable array in ros 5.21 ? just ike this
{a=1;b=3}

thanks;

No it doesn’t work in v5.x