Процессы вызова цикла и присвоение значений в Tcl - PullRequest
0 голосов
/ 10 июля 2019

В настоящее время я использую цикл для итерации значений в процесс (соседей) в Tcl.

for {set i 0} {$i < $val(nn)} {incr i} {
    for {set j 0} {$j < $val(nn)} {incr j} {
        $ns at 0.0 "neighbors $node($i) $node($j) $i $j"
    }
}

Вышеуказанные значения позволяют использовать все необходимые мне значения. Однако внутри процесса некоторые значения присваиваются (списку) и больше не нуждаются в цикле. Краткий фрагмент процесса:

} else {
    puts "..... Do nothing ....  $nd1 - $nd2"
    if {([lsearch -exact $heads $nd1] != -1) || ([lsearch -exact $members $nd1] != -1) } { 
        incr $nd1 
    }
}

Это конец цикла в процессе. puts - это просто маркер, но он проверяет, содержится ли элемент в любом из двух двух списков. Если он есть в любом списке, увеличьте его и перейдите к следующему возможному значению. Это значение больше не нужно проверять / перебирать, поскольку оно уже помещено в список.

Как предотвратить дальнейшее использование значения? Цикл «вызывающий процесс» ВСЕГДА переопределяет то, что происходит в процессе, поэтому даже назначенные значения будут продолжать использоваться. Есть ли другой способ вызова процессов в Tcl? Или, по крайней мере, другой способ передачи значений процессу в Tcl? Или, думаю, вытащить их?

Как примечание, вот мой процесс, который я хочу передать (n1 и n2 - ячейки памяти, nd1 nd2 - фактические числовые идентификаторы)

set heads {}
set members {}


proc neighbors {n1 n2 nd1 nd2} {
global heads members bool allNodes 
    puts "Members --- $members"
    puts "heads --- $heads"
    if {([lsearch -exact $heads $nd1] == -1) && ([lsearch -exact $members $nd1] == -1) } { 
        lappend heads $nd1
        set currentHead $n1
        puts "Current Head: $currentHead $n1 $nd1"
    } else {
        puts "..... Do nothing ....  $nd1 - $nd2"
        if {$nd1 in $heads || $nd1 in $members} then return
#here I want it to go to the next nd1 value and NEVER use it again if it 
#has already been processed 
    }
#Otherwise, do neighbor test with nd2 

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Если операция neighbors является симметричной (часто имеет значение true), вы проверяете все на соответствие всем остальным, как это:

for {set i 0} {$i < $val(nn)} {incr i} {
    for {set j $i} {$j < $val(nn)} {incr j} {
        $ns at 0.0 [list neighbors $node($i) $node($j) $i $j]
    }
}

с внутренним циклом, начинающимся с $i (или [expr {$i - 1}], если вы не хотите проверять вещи против себя) вместо нуля.Это гарантирует, что $j всегда не меньше, чем $i, эффективно (приблизительно) вдвое уменьшая объем работы, который вам нужно сделать.(Точка стиля: считается хорошим стилем использовать [list ...] для подготовки кода для последующего выполнения, а не "..."; первый - более эффективен , а у последнего случаются некрасивые случаи при работе со значениями, которыеможет иметь пробелы.)

То, что вы не можете сделать (по крайней мере, нелегко; может быть, есть способ сделать это), это использовать результат операции neighbors, чтобы остановить будущие вызовы neighbors от того, что произошло, поскольку вы уже запланировали, что они произойдут к тому времени, когда любой из них сможет высказать свое мнение.Вероятно, в вашем случае проще сохранить переменную состояния и проверить ее на предмет возможности досрочного отклонения.Это фундаментальное ограничение использования отложенного вызова команды вместо прямого: передача значений обратно для таких вещей, как пропуск будущих итераций, довольно сложна (и сложна до Tcl 8.6; в ней есть coroutine, что значительно упрощает задачу).

0 голосов
/ 10 июля 2019

Такое чувство, что вы хотите сделать это:

proc neighbors {n1 n2 nd1 nd2} {
    global heads members bool allNodes 
    if {$nd1 in $heads || $nd2 in $members} then return
    ... do the neighborly stuff ...
}

См. https://tcl.tk/man/tcl8.6/TclCmd/expr.htm#M15 для оператора in.

...