Работа с массивами или когда массив распадается на указатели
Добавлено: 20 май 2020, 17:42
Читая примеры и документацию понимаешь, что объявить массив можно по разному:
Но почему-то все упускают из внимания, что выше можно выделить два разных типа массива.
Первый тип:
Второй тип:
При простых операциях вы не заметите в них разницу, но когда пойдут циклы и ветвления можно наступить на грабли и потерять много времени.
И так простой пример который покажет разницу между ними:
прежде чем посмотреть ответ подумайте что должно получится.
ожидаемо.
теперь изменим тип массива:
и получаем посхалку:
можно предположит, что в данном случаи массив содержит директиву static, но это не так - если запустит скрипт сразу второй раз, то вы увидете другой результат. Скорее всего, это происходит по причине того, что когда вы высвобождаете массив, RouterOS не восвобождает память сразу, а только по требованию и если запросить массив с таким же именем, то он отдаст всю начинку этого массива от предыдущего вызова скрипта. Это более наглядно видно при работе с большими структурами.
Второй нежданчик более критичен.
попробуйте понять что тут должно произойти зная первую фичу и запуская скрипт несколько раз:
Если вы немного усложните скрипт, то увидете, что ключи в разных массивах будут указывать на одни и те же значения.
В принципе этим можно пользоваться в некоторых сценариях, или нет, но знать это надо. А то можете потерять несколько дней на поиск блохи, как произошло это у меня.
Старайтесь при инициализации массива использовать конструкцию [:toarray ""]
Код: Выделить всё
:global ar [:toarray "1,2,3"]
:global ar {1;2;3}
:global ar {"n1";"n2";"n3"}
:global ar ({})
:global ar [:toarray ""]
Первый тип:
Код: Выделить всё
:global ar ({})
:global ar {"n1";"n2";"n3"}
Код: Выделить всё
:global ar [:toarray "1,2,3"]
:global ar [:toarray ""]
И так простой пример который покажет разницу между ними:
Код: Выделить всё
:local ar do={
:local x [:toarray ""];
:set ($x->$arg) $arg;
:return $x;
}
:log info [$ar arg=1];
:log info [$ar arg=2];
:log info [$ar arg=3];
теперь изменим тип массива:
Код: Выделить всё
:local ar do={
:local x ({});
:set ($x->$arg) $arg;
:return $x;
}
:log info [$ar arg=1];
:log info [$ar arg=2];
:log info [$ar arg=3];
Второй нежданчик более критичен.
попробуйте понять что тут должно произойти зная первую фичу и запуская скрипт несколько раз:
Код: Выделить всё
:log info "run";
:local ar1 ({});
:local ar2 {"ar2-st0";"ar2-st1";"ar2-st2"};
:log info $ar1;
:for i from=0 to=2 do={
:if ($i = 2) do={:set ($ar1->i) ($ar2->i);}}
:log info $ar1;
:set ($ar2->2) "test";
:log info $ar1;
:log info $ar2;
:log info "end\r\n";
В принципе этим можно пользоваться в некоторых сценариях, или нет, но знать это надо. А то можете потерять несколько дней на поиск блохи, как произошло это у меня.
Старайтесь при инициализации массива использовать конструкцию [:toarray ""]