Reputation: 83
% set HI 1
1
% if { [ info exists HI] && { $HI == 1 } } { puts "Hello World "}
can't use non-numeric string as operand of "&&"
%
Either of the conditions can be tested alone. How to make the && of the tests work in TCL?
This alone works
% if { $HI == 1 } { puts "Hello World "}
Hello World
And this works alone too.
% if { [ info exists HI] } { puts "Hello World "}
Hello World
Upvotes: 1
Views: 1316
Reputation: 137567
In a Tcl expression, {
…}
enclose a non-substituted literal. (Or a variable name if there's a $
immediately before.) When you have an expression inside, that indicates that you should do either one of these:
{
…}
to (
…)
; parentheses have their normal mathematical interpretation inside expressions.{
…}
to [expr {
…}]
so that the expression is really interpreted as such.The bytecode out of the two cases is virtually identical, so in performance terms it's a wash. You should write whichever is clearer to you. (Myself, I hardly ever use the second form, reserving nesting [expr]
in an expression context for cases where I want to have a non-constant expression fragment. That's actually pretty rare.)
Upvotes: 1
Reputation: 4043
The second part of your test, that is
{ $HI == 1 }
is wrong, because I suppose you made a confusion about the meaning of braces in Tcl. Braces are not the same of ( ... )
, they can't be used in a mathematical expression to change the priority used in evaluation.
Braces are used to compose a string containing spaces and make it appear as a single argument to a Tcl command, but without performing substitutions inside of it.
In your case, the $HI
is not substituted with the value of the HI
variable, so you are forming a string containing all the exact characters you see inside the braces, including the leading and the trailing spaces.
If you do
if {{ $HI == 1 } eq {$HI == 1}} {
puts "same"
} else {
puts "not the same"
}
you'll get not the same
as result. (The eq
performs string comparison inside an expression.)
You wan't get the right meaning neither if you use the double quote character as string delimiter, that is
" $HI == 1 "
In this case, your variable is actually substituted with its value, so its like you have directly written (supposing $HI
is 1
, as in your code):
" 1 == 1 "
but it's string, again.
Why Tcl complains? As it says, you are trying to use a non numeric string as operand of &&
, and { $HI == 1 }
is not numeric because there is no way to see is as a number, so Tcl can't convert to a true/false value depending on the number (false if 0, true if not 0), and the error occurs.
I think what you really wanted to write was
if { [ info exists HI] && ( $HI == 1 ) } { puts "Hello World "}
# ^ ^
# |__________|____ note ( ) instead of { }
to give higher priority to the ==
with respect to &&
, or to make the conditional more clear. expr
, which is implicitly called inside the test condition of an if
, knows about the round brackets with the same meaning you find in other programming languages and in math: changing the evaluation order.
As it has been pointed out in other answers and comments, you really don't need the brackets, there, because (as in C and many other languages) the equal operator ==
has a higher priority than the boolean and &&
. But if you want, you can use ( ... )
without fear:
if {2 - 1 * 2} { puts yes } { puts no }
gives no
, because the expression is evaluated as 2 - (1 * 2)
which is 0.
if {(2 - 1) * 2} { puts yes } { puts no }
gives yes
because (2 - 1) * 2
is 2.
Upvotes: 5
Reputation: 30273
You don't need the extra curly braces; this should work fine:
if { [info exists HI] && $HI == 1 } { puts "Hello World" }
Upvotes: 5