The reason why set x [if {1} {return 2} {return 3}] does not work as you expect is, as already noted, the fact that return is the command that causes the script to complete the evaluation. The workaround, using the give procedure, demonstrates that, by default, the return command completes level 1 of the call stack.
However, the "workaround" is indeed a pointless exercise in masochism: the return command allows you to specify where to return using the -level option introduced in Tcl 8.5. Try it, see how it works for you.
set x [if {1} {return -level 0 2} {return -level 0 3}]
source share