Attempt to use a while loop for the 'next' arg of a for loop generates #arg error
Am attempting to teach myself to program using Tcl. The task i've set myself to motivate my learning of Tcl is to solve the 8 queens problem. My approach to creating a program is to successively 'prototype' a solution.
I have asked an earlier question related to the correctly laying out the nested for loops and received a helpful answer. To my dismay I find that the next development of my code creates the same interpreter error : "wrong # args" I have been careful to have an open brace at the end of the line preceding the while loop command. I've also tried to put the arguments of the whileloop in braces. This generates a different error. I have sincerely tried to understand the Tcl syntax man page - not too successfully - suggested by the answerer of my earlier question. Here is the codeset allowd 1
set notallowd 0
for {set r1p 1} {$r1p <= 8} {incr r1p } {
puts "1st row q placed at $r1p"
;# re-initialize r2 'free for q placemnt' array after every change of r1 q pos:
for {set i 1 } {$i <= 8} {incr i} { set r2($i) $allowd }
for { set r2($r1p) $notallowd ; set r2([expr $r1p-1]) $notallowd ;
set r2([expr $r1p+1]) $notallowd ; set r2p 1} {$r2p <= 8} {
;# 'next' arg of r2 forloop will be a whileloop :
while r2($r2p)== $notallowd incr r2p } {
puts "2nd row q placed at $r2p" ;# end of 'commnd' arg of r2 forloop
}
}
Where am I going wrong?
EDIT : to provide clear reply @slebetman
As stated in my text, I did brace the arguments of the whileloop (indeed that was how i first wrote the code) below is exactly the layout of the r2 forloop tried:for { set r2($r1p) $notallowd ; set r2([expr $r1p-1]) $notallowd ;
set r2([expr开发者_运维百科 $r1p+1]) $notallowd ; set r2p 1} {$r2p <= 8} {
;# 'next' arg of r2 forloop will be a whileloop :
while { r2($r2p)== $notallowd } { incr r2p } } {
puts "2nd row q placed at $r2p" ;# end of 'commnd' arg of r2 forloop
}
but this generates the fatal interpreter error : "unknown math function 'r2' while compiling while { r2($r2p .... "
While expects only two arguments. So your code should be:
while {$r2($r2p) == $notallowd} {incr r2p}
though I have to say, that's a weird palce to put a while
.
As for your second problem of an error generated while trying to access the array r2
, the problem is you didn't use $ substitution to get to that value. That is a slightly different problem which stems from a misunderstanding of how variables work in Tcl.
Tcl variables don't really work the same way as variables in other languages. To access the value of a variable you must either use the return value of the set
command (for example [set r2p]
) or, as a shortcut, use $ substitution by appending the $ character in front of your variable name (for example $r2p
). On the other hand, to manipulate a variable you must use the variable name itself without the $ sign (for example r2p
).
This is not really as strange as it sounds. This works exactly the same way pointers work in C only C uses the * character instead of $.
What was happening with your code is that the expr parser (which is what is used by while
, if
, for
etc to handle expressions) looks at your r2($r2p)
and doesn't recognize it as a variable access and so tries to execute it as a mathfunc (like sin()
or tan()
or round()
) which then fails because there is no r2()
function.
Additional explanation:
It should be noted that neither for
nor while
are part of tcl syntax. They are merely functions/commands that you call. Like in any other language, how a function accepts its arguments depends on how it was written. So to figure out how to use while
or for
you really need to read the documentation for them instead of the tcl syntax documentation.
Read my reply to this other question for a more detailed explanation of what's going on: evaluating an expression to true in a if statement with Tcl
精彩评论