Невозможно изменить значение переменной
-
22-09-2019 - |
Вопрос
Я использую симулятор дискретных событий под названием ns-2, который был построен с использованием Tcl и C ++.Я пытался написать какой-то код на TCL:
set ns [new Simulator]
set state 0
$ns at 0.0 "puts \"At 0.0 value of state is: $state\""
$ns at 1.0 "changeVal"
$ns at 2.0 "puts \"At 2.0 values of state is: $state\""
proc changeVal {} {
global state
global ns
$ns at-now "set state [expr $state+1]"
puts "Changed value of state to $state"
}
$ns run
Вот результат:
At 0.0 value of state is: 0
Changed value of state to 0
At 2.0 values of state is: 0
Значение state, похоже, не меняется.Я не уверен, делаю ли я что-то неправильно при использовании TCL.У кого-нибудь есть идея относительно того, что здесь может пойти не так?
Редактировать:Спасибо за помощь.На самом деле, ns-2 - это то, над чем у меня нет особого контроля (если только я не перекомпилирую сам симулятор).Я опробовал предложения, и вот результат:
для кода:
set ns [new Simulator]
set state 0
$ns at 0.0 "puts \"At 0.0 value of state is: $state\""
$ns at 1.0 "changeVal"
$ns at 9.0 "puts \"At 2.0 values of state is: $state\""
proc changeVal {} {
global ns
set ::state [expr {$::state+1}]
$ns at-now "puts \"At [$ns now] changed value of state to $::state\""
}
$ns run
результатом является:
At 0.0 value of state is: 0
At 1 changed value of state to 1
At 2.0 values of state is: 0
И для кода:
set ns [new Simulator]
set state 0
$ns at 0.0 "puts \"At 0.0 value of state is: $state\""
$ns at 1.0 "changeVal"
$ns at 9.0 "puts \"At 2.0 values of state is: $state\""
proc changeVal {} {
global ns
set ::state [expr {$::state+1}]
$ns at 1.0 {puts "At 1.0 values of state is: $::state"}
}
$ns run
результатом является:
At 0.0 value of state is: 0
At 1.0 values of state is: 1
At 2.0 values of state is: 0
Похоже, это не работает...Не уверен, проблема ли это в ns2 или в моем коде...
Решение
Редактировать:теперь понимание государственной машины
Во-первых, используемый вами синтаксис цитирования может доставить вам неприятности.Как правило, вы должны создавать команды Tcl с использованием list, это гарантирует, что Tcl не будет расширять то, чего вы не хотите, чтобы он расширял.
Ваш at-now
вызовы заменяют state
переменная, когда вы совершаете вызов (т.е.когда значение остается неизменным и равно 0.То, что вы хотите, это:
$ns at-now 0.0 {puts "At 0.0 value of state is: $::state"}
$ns at-now 2.0 {puts "At 2.0 value of state is: $::state"}
Это выглядит как ваш changeVal
правильно написано (в первой версии были некоторые из тех же проблем с заменой), а также тот факт, что вы передавали ссылки на переменные, которые будут использоваться локально, и, следовательно, не устанавливали глобальное состояние.
Решение части первой версии вопроса - Используйте глобальные ссылки и цитируйте оба [
и $
чтобы предотвратить замену в точке вызова:
$ns at-now "set ::state \[expr {\$::state + 1}\]"
или, используя фигурные скобки:
$ns at-now {set ::state [expr {$::state + 1}]}
Другие советы
Проблема в том, что вы подставляете значение своих переменных немедленно, а не во время вычисления кода.Вам нужно отложить замену.Таким образом, вместо:
$ns at 2.0 "puts \"At 2.0 values of state is: $state\""
Сделай это:
$ns at 2.0 {puts "At 2.0 values of state is: $state"}
Хорошей практикой является использование чего-либо более сложного, чем простой вызов команды без подстановка в процедуре при выполнении подобного вызова.Гораздо проще заставить его работать правильно.
[ПРАВИТЬ]
Кроме того, в at-now
все еще откладывает выполнение своего тела до окончания текущего at
ВОЗВРАТ.
Я не уверен, почему это работает, но это работает:
set ns [new Simulator]
set state 0
proc changeVal {} {
global ns
incr ::state
$ns at-now {puts "Local::At [$ns now] values of state is: $::state"}
}
$ns at 0.0 "puts \"Global::At 0.0 value of state is: $state\""
changeVal
$ns at 9.0 "puts \"Global::At 2.0 values of state is: $state\""
$ns run
Выходной сигнал:
Global::At 0.0 value of state is: 0
Local::At 0 values of state is: 1
Global::At 2.0 values of state is: 1
Если кто-нибудь знает объяснение, это было бы здорово.