Version 19 of boilerplate

Updated 2006-04-26 01:45:54

standarized text or formula [L1 ]

Here's a Wiki location for those code snippets and idioms that might well belong in every script you write.

LV hopes that people explain why for the novices that stumble across the page...


Here's a way to have a procedure accept its arguments both "whole" (as a list) or in pieces, which may sometimes be helpful (RS):

 proc foo { args } {
      if {[llength $args] == 1} {set args [lindex $args 0]}
      ...
 }

I've been thinking this a lot and still can't figure out, what is so cool about this code. Can you explain a bit more, what is the idea behind this? --mjk - RS: It's very simple. Say you have a max function to return a numeric maximum:

 proc max list {lindex [lsort -real $list] end}

Now if you want to call this with discrete values, you'd have to listify them:

 puts [max [list $foo $bar $grill]]

But with the above boilerplate code, you can have it both ways:

 proc max args {
    if {[llength $args]==1} {set args [lindex $args 0]}
    lindex [lsort -real $args] end
 }
 puts [max $foo $bar $grill]
 puts [max $myValueList]

OK. Now I got it. Thanks. --mjk


Phil Ehrens says nearly every executable script should start with this:

 if { [ regexp {(root|wheel)} $::env(GROUP) ] } {
    puts stderr "DID YOU REALLY MEAN TO RUN $::argv0 AS ROOT?"
    exit 666
 }

LV notes for the novice that it is seldom a good idea to accidentally run miscellaneous commands while in the root or wheel group on Unix, as those groups often have write permission on files that should not be changed accidentally. There's also the possibility of doing something intentionally that should not be done - like the story of the novice who deleted all the files out of the root file system that he believed were not needed... resulting in a system that no longer ran...

RJ For the record, I was not a novice.


RS 2006-04-20: I have taken up the habit to structure stand-alone scripts as follows:

 #!/usr/bin/env tclsh
 set usage {
    ...
 }
 if {[llength $argv] != ...} {puts stderr $usage; exit}
 proc main argv {
    foreach {...} $argv break
    ...
 }
 proc ...
 ...
 main $argv

The usage message comes first, both for source code documentation and "online help" which is displayed when the script is called with no arguments. With the main proc I can design things top-down, and it is compiled, and its variables are typically local, which both should increase performance.


Donald Arseneau: What reminds me most of "boilerplate" is the long-recommended incantation

 #!/bin/sh
 #  Restart with tclsh \
 exec tclsh "$0" "$@"

placed at the top of a Tcl program, in order to invoke tclsh installed in an unknown location. Recently, many people prefer the simpler

 #!/usr/bin/env tclsh

but /usr/bin/env still does not exist on several systems. See exec magic for full explanation of these and similar forms.

I recently question the value of the former, older, method as emacs and some other editors recognize the sh invocation and provide syntax highlighting appropriate for shell scripts, not Tcl.

(Thanks for the push Lars H.)


Donald Arseneau: Another good habit to get into, which fits the boilerplate theme, is

  package require Tcl 8.4

where the version number is the version you use for development, or which you conciously target for support. Then, on the chance that the program gets run under, say, Tcl 8.0, there is a a clear message for why it fails. There is no complaint when the installed Tcl version is higher than requested.


Category Glossary | Category Tutorial