Tcl:列表内的持久增量

Tcl: Persistent increment inside a list

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

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 专家,所以如果我试图以错误的方式完成此操作,请告诉我。 :)

在此先感谢您的帮助。

我希望这样做 这个:

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

会递增该列表中的每个数值,这就是我相信你想要做的。然而,做 这个:

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

不会工作。 Tcl 从概念上将子列表项从 foreach 中的主列表中复制出来,这样对 pair 的更改就不会反映回来。此外,从概念上讲,Tcl 首先也会复制要交给 foreach 的值。当然,这些复制品并不是真的,因为那会非常昂贵!相反,Tcl 使用具有写时复制到共享语义的共享引用,这个系统工作得很好,因为我们可以非常便宜地检查共享状态(这是由 Tcl 的线程模型启用的;值为 never 在线程之间共享,因此共享状态决策可以是无锁的和本地的。

这样做的结果是 Tcl 明确拒绝奇怪的远距离状态更改,这种更改有时会在具有不同语义的语言中导致奇怪的错误。如果您要更改某些内容,它最好是一个变量(因为这些是主要的可变内容),并且当您进行更改时,它就在您面前。

如果你稍微改变你的数据结构使其变平而不是使用成对列表,它就可以用作字典。还有一个 dict incr 命令:

This adds the given increment value (an integer that defaults to 1 if not specified) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to 0. It is an error to increment a value for an existing key if that value is not an integer. The updated dictionary value is returned.

用法示例:

% 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