The following piece of code produces the error:
can't read "n": no such variable
while executing
"$ns duplex-link $n$i $n([expr ($i+1)%120]) 1Mb 10ms DropTail"
("for" body line 2)
invoked from within
"for {set i 7} {$i < 120} {incr i} {
$ns duplex-link $n$i $n([expr ($i+1)%120]) 1Mb 10ms DropTail
}"
(file "multicast.tcl" line 44)
it seems $n$i is not evaluated to the required format of $n7 etc. Any help in the solution is much appreciated.
for {set i 0} {$i < 120} {incr i} {
set n$i "[$ns node]"
global n$i
}
# Create links
$ns duplex-link $n0 $n1 1.5Mb 10ms DropTail
$ns duplex-link $n0 $n2 1.5Mb 10ms DropTail
$ns duplex-link $n2 $n3 1.5Mb 10ms DropTail
$ns duplex-link $n2 $n4 1.5Mb 10ms DropTail
$ns duplex-link $n1 $n7 1.5Mb 10ms DropTail
$ns duplex-link $n1 $n5 1.5Mb 10ms DropTail
$ns duplex-link $n4 $n6 1.5Mb 10ms DropTail
#create the rest of the links
for {set i 7} {$i < 120} {incr i} {
$ns duplex-link $n$i $n([expr ($i+1)%120]) 1Mb 10ms DropTail
}
For clarity, I would introduce some temp vars:
An invocation of set with only a single arg (the name of a var) returns the value of that variable.
Alternatively, you could use the subst command:
Tcl's
$
syntax does not parse non-alphanumeric variable names (with a few exceptions I'll come to in a moment) so it stops trying to parse the first part of$n$i
after then
. This is a limitation of the parser but Tcl itself allows almost anything in.One of those exceptions is that
::
namespace separators are allowed too, and another is that you can put a complex literal variable name in{
braces}
, like${n$i}
. That's not helpful here though, as you can't substitute variables into variable names that way.What you should do
Use an array. The form
$somename(stuff-to-do-an-index)
allows a full range of substitutions in thestuff-to-do-an-index
, except for some restrictions on parentheses that hardly ever matter.Other alternatives
You can use the one-argument version of
set
to read from variables (it's documented, but a little obscure to those new to Tcl).You can also use
upvar 0
to make an alias to the variable which you can then manipulate normally:Even more ugly would be this construction with
subst
:After that, it gets really nasty with
eval
andreturn -level 0
(which is actually efficient: strange but true!) and all sorts of stuff like that, but really don't go that way. Arrays are perfect for this sort of thing, really.