Why do Tcler suggest to brace your `expr`essions?
tcl
Solution
The "problem" with `expr` is that it implements its own "mini language", which includes, among other things, variable substitution (replacing those `$a`-s with their values) and command substitution (replacing those `[command ...]` things with the results of running `command`s), so basically the process of evaluating `expr $a + $b` goes like this:
- The Tcl interpreter parses out four words — `expr`, `$a`, `+` and `$b` out of the source string. Since two of these words begin with `$`, variable substitution takes place so really there will be `expr`, `1`, `+`, and `2`.
- As usually, the first word is taken to be the name of a command, and others are arguments to it, so the Tcl interpreter looks up a command named `expr`, and executes it passing it the three arguments: `1`, `+`, and `2`.
- The implementation if `expr` then concatenates all the arguments passed to it interpreting them as strings, obtaining a string `1 + 2`.
- This string is then parsed again — this time by the `expr` machinery, according to its own rules which include variable- and command substitutions, as already mentioned.
What follows:
- If you brace your `expr`essions, like in `expr {$a + $b}`, grouping provided by those curly braces inhibits interpretation by the Tcl interpreter1 of the script intended to be parsed by `expr` itself. This means in our toy example the `expr` command would see exactly one argument, `$a + $b`, and will perform substitutions itself.
"Double parsing" explained above might lead to security problems.
For example, in the following code
set a {[exec echo rm -rf $::env(HOME)]}
set b 2
expr $a + $b
The `expr` command will itself parse a string `[exec echo rm -rf $::env(HOME)] + 2`. Its evaluation will fail, but by that time, the contents of your home directory will be supposedly gone. (Note that a kind Tcler placed `echo` in front of `rm` in a later edit to my answer in an attempt to save the necks of random copypasters, so the command as written won't call `rm` but if you remove `echo` from it, it will.)
- Double parsing inhibits certain optimisations the Tcl engine can do when dealing with calls to `expr`.
1 Well, almost — "backslash+newline" sequences are still processed even inside `{...}` blocks.
Problem
We can evaluate the two expression in two possible ways: ``` set a 1 set b 1 puts [expr $a + $b ] puts [expr {$a + $b } ] ``` But why hate experienced Tclers the first one, and consider it as bad practice? Does the first usage of `expr` has some security concern?