我可以边走边修改 Tcl struct::graph 吗?

Can I modify a Tcl struct::graph while walking it?

Tcl struct::graph 有一个 walk 命令,我想用它来删除节点并清理节点属性可访问的数据,例如小部件名称。该文档没有说明在遍历图形时可以做什么和不能做什么,所以我想知道如果我开始删除与行走节点相邻的弧,它是如何工作的。

这是我想要的步行命令(即将完成,可能有错误):

proc csp_scene_walk_remove {mode g n} {
  set canvas [$g get canvas]
  foreach arc [$g arcs -adj $n] {
    $canvas delete [$g arc get $arc widget]
  }
  $canvas delete [$g node get $n widget] [$g node get $n widgetanno] [$g node get $n widgetanno].bg
  $g node delete $n
}

我想如果 walk 适用于实际的图形对象而不是副本,我想它可能会起作用,数据在适当的时候在内部复制等。

问:stuct::graph walk 如果边走边修改图,会有什么行为?


编辑: 该命令似乎可以像这样使用它来执行我想要的操作:

# destroy all nodes downstream with associated widgets
mygraph walk $node -order post -type dfs -dir forward -command csp_scene_walk_remove;

但我无法判断这是否是 Tcllib 所见的实现定义行为。

虽然您正在做的事情会奏效,但您的怀疑是正确的,因为并发修改错误很难解决。因此,最简单的方法是在遍历树时累积要删除的节点列表,然后使用 $graph node delete {*}$theNodes 将它们全部删除。除了我们可以保留我们在图形本身中积累的节点列表,这会稍微简化一些事情。

proc csp_scene_walk_remove {mode g n} {
    upvar #0 $nodeAccumulator nodes
    set canvas [$g get canvas]
    foreach arc [$g arcs -adj $n] {
        $canvas delete [$g arc get $arc widget]
    }
    $canvas delete [$g node get $n widget] [$g node get $n widgetanno] \
            [$g node get $n widgetanno].bg
    $g lappend deadNodes $n
}

mygraph set deadNodes {}
# Order of traversal is unimportant; nodes remain until afterwards
mygraph walk $node -command csp_scene_walk_remove
# NB: Expanding substitution is very useful here!
mygraph node delete {*}[mygraph get deadNodes]
mygraph unset deadNodes

我更想给每个节点的 canvas 项目一个公共标签(例如,节点 ID!),然后用它来删除它们,这样我就不需要跟踪 canvas 很多东西的ID,但这取决于你...