Catch error result unexpected

I missed something very basic but still don’t understand a cause:

% catch {expr 1/0} result
% puts $result # returns 'divide by zero'


% set script {expr 1/0}
% catch {$script} result
% puts $result # returns 'invalid command name "expr 1/0"'

An explanation and correction would be very appreciated.

I found a way to get the expected result using ‘eval’:

catch {eval $script} result

Still need an explanation what’s going on behind the scene and why catch {$script} result in the previous example doesn’t works.

Referring to the 12 rules, it’s a question of how many times things are evaluated. In the first example, the command is broken into words, and then catch will evaluate expr 1/0 – this 2nd evaluation is just like the first: break it into words, substitute variables, etc.

In the 2nd example, the braces delay variable substitution. So catch gets $script. It evaluates that into the string “expr 1/0”, but there is no 3rd evaluation, so it attempts to execute that string as a command.

As you’ve seen, adding eval gives you that 3rd round of evaluation.

The simpler approach is to omit the braces: catch $script result