if 0 {

SB: Somebody care to explain why this search give so many hits?

https://wiki.tcl-lang.org/2?if+0+{*

NEM - It's used a lot in pages which are mostly code. By surrounding the non-code explanation parts in

if 0 {

This is some explanation

}

Then the whole page can be copied and pasted into a tclsh/wish/tkcon without the explanation bits causing an error. It's just a way of doing block commenting.

AMG: Wiki pages using this style need to be careful that they match braces. Curiously, this means they can't link to this page to explain their style, as this page's title has a mismatched brace! Or they could put a seemingly stray close brace following the link, but such is likely to be "fixed" by wikignomes hunting for typos.

Ro 2005-11-29: The answer is -- it's the multiline comment in Tcl. There is no other multiline comment facility. The tcl way of doing if 0 {} is actually ridiculously bad, as you have to have balanced braces in the comment or your script won't run.

escargo 16 Mar 2003 - Isn't part of the point of this construct that no bytecodes get generated for any of the text included inside the curly braces? This removes any runtime penalty for including useful info (however structured) inside those braces?

NEM Yes, that's true. I imagine normal Tcl comments produce no bytecode too, though. The runtime efficiency of comments is generally not something to worry about unless you need serious performance, in which case you should probably be thinking about moving to C or some other language for that task.

escargo I thought ordinary comments (that is with the # command) got parsed and substituted, etc. Does that step get skipped for the the if 0... construct?

NEM I'm out of my depth now. I'm really not sure what happens with comments, especially when the byte-compiler is involved. I don't think comments get substituted, as this example demonstrates:

 % # [set a 1]
 % set a
 can't read "a": no such variable

From this, I would assume that comments produce no bytecode, but I'll defer to someone who actually knows. Another quick test is the following:

 % proc test1 {args} {}
 % proc test2 {args} {
 # This is a long set of comments with [substitions]
 # of various forms: $args. {} Blah blah blah
 }
 % proc test3 {args} {
 if 0 {
 This is a long set of comments with [substitutions]
 of various forms: $args. {} Blah blah blah
 }
 }
 % time test1 100000
 1 microseconds per iteration
 % time test2 100000
 27 microseconds per iteration
 % time test3 100000
 28 microseconds per iteration
 % info patchlevel
 8.4.2

So, from this it seems that a proc with comments in is not optimized away like the empty proc is. Also, there appears to be little or no difference between a standard comment and an if 0 block, at least for very small tests. Neither proc throws an error (from the bad command name substitutions), so I think neither performs substitutions. I also did a bigger test by using [string repeat] to build up a long comment and then defining the same procs as above, with the longer comment (14000 characters), and the times were roughly equivalent (although the if 0 construct was a couple of microseconds longer each time).


MS answers:

  • a proc where (a) the argument list is {args} and (b) the body is all spaces is compiled to just "substitute the arguments (in case there are any side-effects), then push an empty result". Procs where the body consists of comments are not optimised this way, in order to reduce the compile-time overhead. Remember that this optimisation was introduced as a way to allow fast assertions in Tcl.
  • all other procs compile "subst and push the arguments, call the proc"
  • standard comments compile to strictly nothing
  • "if 0 { ... }" compiles to "push an empty result"

BTW, your test here is hitting bug #458361 [L1 ], so that the proc body is parsed and compiled at each call. In order to avoid that and do a fair test, do call instead

   time {test2 } 100000

Witness the results:

 % time test1 100000
 1 microseconds per iteration
 %  time test2 100000
 25 microseconds per iteration
 % time test3 100000
 21 microseconds per iteration
 % time {test2 } 100000
 4 microseconds per iteration
 % time {test3 } 100000
 4 microseconds per iteration

DKF - The if 0 {...} construct does result in bytecodes not being generated for the body, though this doesn't usually make that much difference since the best that you could do would be to skip about two bytecodes...


RS 2013-11-28: Another use for if 0 is a sequence of if/elseif/elseif branches, where you might want to swap the order. In

 if {$condA} {
    ...
 } elseif {$condB} {
    ...
 } elseif {$condC} {
    ...
 }

it is easy to swap the sequence of condB and condC, by cut & paste in the editor. However, to swap the sequence of condA and condB takes more delting resp. inserting text. If you start this if command with 0, all branches are elseif branches and can be easily rearranged:

 if 0 {
 } elseif {$condA} {
    ...
 } elseif {$condB} {
    ...
 } elseif {$condC} {
    ...
 }

AMG: I recently tried this style in C with great success. It was very important because the parts of the if construct were supplied by preprocessor macros, and I didn't want to have a different macro for the first test versus all the subsequent. So instead I had a macro expanding to "if (0)" (expecting the user to supply the trailing semicolon so it resembles a function call).

Unfortunately, this triggered an ill-advised warning in the target compiler (not gcc): condition is always false. The customer did not want warnings, and I didn't want to give them warnings, so I had to do something else. I wish I could have instead convinced them to use a better compiler, but they were already in over their head wrangling the GUI IDE visual whatever they had... give them something where they have to (gasp!) type "make", and they would have no hope.

See Also

Literate programming in a wiki