2010-03-29 9 views
1

Я использую дискретный симулятор событий, называемый 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 

Значение состояния, кажется, не меняется. Я не уверен, что я делаю что-то неправильно в использовании TCL. У кого-нибудь есть идея относительно того, что здесь может быть неправильным?

EDIT: Спасибо за помощь. На самом деле, 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 или мой код ...

+2

Вы считаете 'incr state' вместо' set state [expr {$ state + 1}] '? –

+0

Да. Просто попробовал ... не работает. – Legend

+0

он должен с глобальным refs –

ответ

2

Edit: теперь понимает состояние машины

Во-первых, со ссылкой на синтаксисом «Использование будет затруднено. Вы должны, как правило, создавать команды Tcl с помощью списка, это гарантирует, что Tcl will not expand what you don't want it to expand.

Ваши 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}]} 
+0

Спасибо за ответ. Поскольку ns-2 является симулятором, мне придется перекомпилировать его, чтобы включить изменения, которые вы предложили. Я буду работать над этим. Что касается других вещей, я просто обновил свой пост. Спасибо за ваше время. – Legend

+0

@Legend, я обновился, чтобы дать более четкий ответ (b/c. Я перечитаю вопрос более внимательно). Были две проблемы для преодоления, и я просто ответил на менее важный вопрос. Этот ответ должен решить ваши проблемы без необходимости изменения ns-2. –

+0

Спасибо Трей ... Для всех, кому интересно знать правильную часть кода, ищите мой ответ здесь. – Legend

2

Проблема вы подставляя значение ваших переменных сразу, а не во время оценки кода. Вам нужно отложить замену.Таким образом, вместо того, чтобы:

$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"} 

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

[EDIT]
Кроме того, at-now все еще откладывая не делает его тело, пока после текущей at возвращается.

+0

Спасибо. Обновлен мой пост с выходом. Кажется, это не проблема. – Legend

0

Я не знаю, почему это работает, но это работает:

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 

Если кто-нибудь знает объяснение, что было бы здорово.

+0

См. Мой ответ, почему он работает (подсказка: вы изменили порядок команд, что повлияло на то, что было заменено). –