Tcl: постоянное приращение внутри списка - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь настроить несколько incr для каждой записи в списке. Я подумал, что мог бы назначить целое число для каждой записи списка ...

set list { 
      {/run      00}
      {/run/shm  00}
      {/boot     00}
}

и использовать следующий код как часть foreach l oop для увеличения значения ...

lset list 1 [expr {[lindex $list 1] + 1}]

Я обнаружил, что значение увеличивается правильно, но когда код выполняется во второй и третий раз, значение сбрасывается на 00, поэтому оно никогда не увеличивается после 1 при каждом проходе.

Если я установил до базового приращения c для стандартной переменной как части кода ..

set counter 00
incr counter 

оно довольно успешно увеличивается при каждом запуске кода, и счетчик увеличивается на 1, пока я не нарушу код.

Любой совет или помощь в получении этой работы будет принята с благодарностью. Я определенно не эксперт по Tcl, поэтому, если я пытаюсь выполнить sh это неправильно, пожалуйста, дайте мне знать. :)

Заранее спасибо за помощь.

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

Если вы слегка измените свою структуру данных, чтобы выровнять ее вместо использования списка пар, она станет пригодной для использования в качестве диктанта. И есть команда dict incr:

Это добавляет заданное значение приращения (целое число, которое по умолчанию равно 1, если не указано) к значению, с которым данный ключ отображается в значение словаря, содержащееся в данной переменной, записывая полученное значение словаря обратно в эту переменную. Несуществующие ключи обрабатываются так, как если бы они отображались на 0. Ошибка увеличения значения для существующего ключа, если это значение не является целым числом. Возвращается обновленное значение словаря.

Пример использования:

% set list {/run 0 /run/shm 0 /boot 0}
/run 0 /run/shm 0 /boot 0
% dict incr list /boot
/run 0 /run/shm 0 /boot 1
% puts $list
/run 0 /run/shm 0 /boot 1

Если вы хотите сделать это в команде, вы должны передать по имени и использовать upvar поэтому изменения вносятся в правый кадр стека:

% proc demo {fstab_} {
    upvar 1 $fstab_ fstab
    dict incr fstab /run
  }
% demo list
/run 1 /run/shm 0 /boot 1
% puts $list
/run 1 /run/shm 0 /boot 1

И для обновления каждого значения:

% foreach dir [dict keys $list] { dict incr list $dir }
% puts $list
/run 2 /run/shm 1 /boot 2
0 голосов
/ 25 апреля 2020

Я ожидаю, что выполнение this:

for {set idx 0} {$idx < [llength $list]} {incr idx} {
    lset list $idx 1 [expr {[lindex $list $idx 1] + 1}]
}

будет увеличивать каждое значение числительного c в этом списке, что, как я полагаю, вы хотите сделать. Однако выполнение этого:

foreach pair $list {
    lset pair 1 [expr {[lindex $pair 1] + 1}]
}

будет не работать. Tcl концептуально копирует элементы sublist из основного списка в foreach, чтобы изменения в pair не отражались обратно. Кроме того, концептуально Tcl также копирует значение для передачи в foreach. Конечно, эти копии на самом деле не настоящие, так как это будет очень дорого! Вместо этого Tcl использует общие ссылки с семантикой «копировать при записи в общий ресурс» - систему, которая работает очень хорошо, учитывая, что мы можем очень дешево проверить состояние общего доступа (что обеспечивается моделью потоков Tcl; значения никогда разделяется между потоками, поэтому решения о состоянии совместного использования могут быть свободными от блокировки и локальными).

Следствием этого является то, что Tcl явно отклоняет странные изменения состояния на расстоянии, которые иногда вызывают странные ошибки в языках с различной семантикой. Если вы что-то меняете, лучше бы это была переменная (так как это основные изменчивые вещи), и вы будете иметь это прямо перед собой, когда будете вносить изменения.

...