List Tcl:列表中的持久增量

List Tcl:列表中的持久增量,list,tcl,increment,List,Tcl,Increment,我正在尝试为列表中的每个条目设置多个增量。我想我可以给每个列表条目分配一个整数 set list { {/run 00} {/run/shm 00} {/boot 00} } 并使用以下代码作为foreach循环的一部分来增加值 lset list 1 [expr {[lindex $list 1] + 1}] 我发现该值正确递增,但当代码第二次和第三次执行时,该值已重置为00,因此每次执行时,该值不会超过1 如果我将标准变量的基本增

我正在尝试为列表中的每个条目设置多个增量。我想我可以给每个列表条目分配一个整数

set list { 
      {/run      00}
      {/run/shm  00}
      {/boot     00}
}
并使用以下代码作为foreach循环的一部分来增加值

lset list 1 [expr {[lindex $list 1] + 1}]
我发现该值正确递增,但当代码第二次和第三次执行时,该值已重置为00,因此每次执行时,该值不会超过1

如果我将标准变量的基本增量设置为代码的一部分

set counter 00
incr counter 
每次运行代码时,它都会非常愉快地递增,计数器会递增1,直到我破坏代码为止

任何建议或帮助,使这项工作将不胜感激。我绝对不是tcl专家,因此如果我试图以错误的方式完成此任务,请让我知道。:)

提前感谢您的帮助。

我希望这样做:

这是行不通的。Tcl从概念上将子列表项从
foreach
中的主列表中复制出来,这样对
对的更改就不会反映出来。此外,从概念上讲,Tcl还首先将值复制到
foreach
。当然,这些拷贝实际上不是真的,因为那将非常昂贵!相反,Tcl使用共享引用和写时复制到共享语义,这是一个非常有效的系统,因为我们可以非常便宜地检查共享状态(这是由Tcl的线程模型启用的;线程之间从不共享值,因此共享状态决策可以是无锁和本地的)


这样做的一个结果是,Tcl明确拒绝了奇怪的远距离状态更改,这种更改有时会在具有不同语义的语言中导致奇怪的bug。如果你正在改变一些东西,最好是一个变量(因为这些是主要的可变因素),当你做改变时,它就在你面前

如果您稍微更改数据结构以使其扁平化,而不是使用对列表,则它可以作为dict使用。下面有一个命令:

这会将给定的增量值(如果未指定,则默认为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
如果要在命令中执行此操作,必须按名称传递并使用,以便在右侧堆栈帧中进行更改:

% 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

这样做的结果是,
foreach
将看不到从其主体内部对其迭代的列表所做的任何更改:这实际上不是同一个列表。多谢Donal,这就成功了。使用
for
而不是
foreach
更新了每个列表条目的增量,并且它们在代码迭代过程中保持不变。非常感谢您提供有关
foreach
工作的深入信息。我从来没有想到这会是我的问题谢谢肖恩,很高兴知道有多种方法可以剥猫皮:)非常方便。
% 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