4 ms·
Some of these things do not quite work this way, but they demonstrate some interesting peculiarities! The eval should be expr, as you are trying to evaluate a m
by suyjuris 6y ago
Some of these things do not quite work this way, but they demonstrate some interesting peculiarities! The eval should be expr, as you are trying to evaluate a mathematical expression, not a command. Similar to the common footgun:
set a 1
puts [expr $a + $a] # Wrong!
puts [expr {$a + $a}] # Correct
Also $$b expands to $a, not 5, as dollar expansion stops at the next non-alphanumeric-or-underscore character. This would usually be written as [set $b] (equivalent to [set [set b]] ), utilising that the set command outputs the value of the variable with that name. Similarly, [set var[set $b]] for the last line. Also, # is only a special character at the beginning of a statement, so comments have to follow a newline or semicolon.
In the “everything is a string” department, my favourite are block comments:
if 0 {
This is a comment.
}
You can write any kind of comment in there, even special characters like $undefined or [undefined] which would cause errors in normal code. Only wrongly matched {} would be a problem.
- bloaf 6y agomea culpa on the eval/expr. I did the comments inline for brevity. I am confused about the $$ examples though, since swear I have worked on production code that literally behaves like that. Maybe they had some extra non-alphanumeric bits. This behaves the way I gave originally set b a set (a) 5 puts $($b) Edit: I found the production code. There was both puts [expr 3 - $$b] and puts [subst $$b] and the Steve example was actually two steps: set nameVariable [subst var$$b] puts [subst $$nameVariable]
- suyjuris 6y agoYeah, that is another dark corner. I was not quite precise (I forgot this behaviour existed): $ expansion does allow for parentheses as well, so that arrays work. Meaning $($b) is the same as [set ($b)] which is element $b of the array in variable {} (empty string; that is the name of the variable). The docs [1] say: > $name(index) > Name gives the name of an array variable and index gives the name of an element within that array. Name must contain only letters, digits, underscores, and namespace separators, and may be an empty string. [...] Command substitutions, variable substitutions, and backslash substitutions are performed on the characters of index. So that means: set b a set (a) a ;# this sets element a of the variable {} to a puts $($b) ;# prints that element info vars ;# all variables, note that {} is in there puts $($($($b))) ;# Of course this works... [1] http://www.tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M14 http://www.tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M14
- guenthert 6y agoYes, and this everything goes makes it difficult to spot bugs. Perl byte-code compiled a program at start and was able to find a number of bugs (if the warnings option was enabled). If e.g. a variable is misspelled in TCL, you'll find out exactly when that particular line of code is reached. If that happens to be in the error path ...