KBK closed a follow-up to the comp.lang.tcl newsgroup with the advice that, "Also, it's important always, always to brace your expressions. Don't do
set a [expr $b / $c]
but rather
set a [expr { $b / $c }]
Otherwise, your variables may undergo unexpected conversions numeric -> string -> numeric, you can lose precision, your expressions will be much slower, and you can even have security problems:
# don't run set x { [format C:\] } set y [expr $x + 3]
"
AMG: The security problems of unbraced expr expressions very similar to SQL injection attacks. Notice how sqlite's Tcl binding does its own variable expansion to avoid this very problem. Many, many sh scripts have this problem as well because the default is to apply multiple passes of interpretation.
RS: In the following cases braced expressions don't work:
set op + expr $x $op $y
expr [join $intlist +]
KPV: Braced expressions also don't work when you do negation in the lazy way:
set n1 -3 set n2 -$n1 expr {2 + $n2} ;# error expr 2 + $n2 ;# ok
aricb Dec. 10 2005 -- As a bonus, braced expressions are generally much faster than their non-braced counterparts. Here's an attempt to illustrate the difference:
proc time_braces {} { set expressions { {1 + 1} {16 - 7} {(16 - 7)} {7 * 12} {81 / 3} {81 / 5} {16224308 + 123580329} {6.3 + 1.2} {6.3 - 1.2} {6.3 * 1.2} {6.3 / 1.2} {log(765) * 3} {(log(765) * 3) / 8.23} } puts [format " %-22s %-8s %-8s %-8s %-5s" "Expression" "-braces" "+braces" "ratio" "% speedup"] puts " [string repeat - 22] [string repeat - 8] [string repeat - 8] [string repeat - 8] [string repeat - 5]" foreach expression $expressions { set time1 [lindex [time "expr $expression" 100000] 0] set time2 [lindex [time [list expr $expression] 100000] 0] set ratio [expr {$time1 / $time2}] set percent [expr {100 * (1 - ($time2 / $time1))}] puts [format " %-22s %8.6f %8.6f %6.3f:1 %5.2f" $expression $time1 $time2 $ratio $percent] } puts "\n -braces and +braces are in microseconds per iteration" }
Results:
Expression -braces +braces ratio % speedup ---------------------- -------- -------- -------- ----- 1 + 1 2.334690 0.366480 6.371:1 84.30 16 - 7 2.388280 0.359960 6.635:1 84.93 (16 - 7) 3.748160 0.356120 10.525:1 90.50 7 * 12 2.438530 0.368200 6.623:1 84.90 81 / 3 2.456060 0.395680 6.207:1 83.89 81 / 5 2.518490 0.397380 6.338:1 84.22 16224308 + 123580329 2.726690 0.369530 7.379:1 86.45 6.3 + 1.2 3.237970 0.497100 6.514:1 84.65 6.3 - 1.2 3.199230 0.486350 6.578:1 84.80 6.3 * 1.2 3.279100 0.480630 6.823:1 85.34 6.3 / 1.2 3.257540 0.494340 6.590:1 84.82 log(765) * 3 6.202120 0.975590 6.357:1 84.27 (log(765) * 3) / 8.23 7.951270 1.142210 6.961:1 85.63 -braces and +braces are in microseconds per iteration
RS 2007-01-09: These results puzzle me: the expressions contain no variable references, all constants. I thought the time advantage of braced expressions was because they could retrieve the numeric value of variables directly, without having to parse string reps - but in the above cases, the strings would have to be parsed either way...
AM The numeric value of the strings is cached in the data structure that [expr] builds up during the parsing. So there is no real difference between numeric constants and variables with numeric values