Impossibile modificare il valore della variabile
-
22-09-2019 - |
Domanda
Io sto usando un simulatore ad eventi discreti chiamato ns-2 che è stato costruito utilizzando Tcl e C ++. Stavo cercando di scrivere del codice in 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
Ecco l'output:
At 0.0 value of state is: 0
Changed value of state to 0
At 2.0 values of state is: 0
Il valore di stato non sembra cambiare. Non sono sicuro se sto facendo qualcosa di sbagliato nell'uso di TCL. Qualcuno ha un'idea di quello che potrebbe andare male qui?
EDIT: Grazie per l'aiuto. In realtà, ns-2 è qualcosa su cui non ho molto controllo (a meno che io ricompilare il simulatore stesso). Ho provato i suggerimenti ed ecco l'output:
per il codice:
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
l'output è:
At 0.0 value of state is: 0
At 1 changed value of state to 1
At 2.0 values of state is: 0
E per il codice:
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
l'output è:
At 0.0 value of state is: 0
At 1.0 values of state is: 1
At 2.0 values of state is: 0
non sembra funzionare ... Non sono sicuro se il suo un problema con ns2 o il mio codice ...
Soluzione
Modifica: ora comprendere la macchina dello Stato
In primo luogo, la sintassi citando stai usando sta per arrivare nei guai. In generale dovreste costruire comandi Tcl utilizzando l'elenco, questo assicura che Tcl non lo farà espandere quello che non vuoi che espandersi .
Le chiamate at-now
stanno sostituendo la variabile state
quando si effettua la chiamata (vale a dire quando il valore è invariato e 0. Quello che vuoi è:
$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"}
Sembra che la tua changeVal
è correttamente scritta (la prima versione aveva alcuni degli stessi problemi di sostituzione), così come il fatto che si stavano passando in riferimenti variabili che sarebbero stati utilizzati a livello locale, e quindi non impostare lo stato globale.
Soluzione per parte della prima versione di domanda - utilizzare riferimenti globali, e citazione sia la [
e $
per impedire la sostituzione nel punto della chiamata:
$ns at-now "set ::state \[expr {\$::state + 1}\]"
o, usando le parentesi graffe:
$ns at-now {set ::state [expr {$::state + 1}]}
Altri suggerimenti
Il problema è che si sta sostituendo il valore delle variabili immediatamente, e non al momento viene valutato il codice. È necessario rinviare la sostituzione. Così, invece di:
$ns at 2.0 "puts \"At 2.0 values of state is: $state\""
Fare questo:
$ns at 2.0 {puts "At 2.0 values of state is: $state"}
E 'buona pratica di mettere qualcosa di più complesso di una semplice chiamata di un comando senza di sostituzione in una procedura quando si fa una chiamata del genere. Molto più facile per farlo funzionare a destra.
[EDIT]
Inoltre, il at-now
è ancora posponendo facendo il suo corpo fino a dopo il ritorno at
attuali.
Non sono sicuro perché questo funziona, ma funziona:
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
Output:
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
Se qualcuno conosce una spiegazione, che sarebbe grande.