This blog entry is a bit of a Lincoln/Douglas debate I'm having with a fellow Tcler on the nature of
package ifneeded
scripts and how pkgIndex.tcl files come to be.

My debate assertions are as follows:

  1. That Tcl Style Guide (Included in TIP 352) recommends placing a package provide statement in the header of a source file.
  2. That while a package ifneeded script can contain arbitrary code, baking that behavior into a pkgIndex.tcl file is not a sustainable practice.
  3. That it is proper and necessary for a package distributor to produce their own pkgIndex.tcl files.
  4. That a proper technique is to scan source files in a vfspath for the package provide (Recommended in the tip above) and use a routine like the any of the following to produce a master manifest of packages:

My colleague believes in a school of thought that the following construct should be allowed for:

pkgIndex.tcl

package ifneeded ego 0.1 [list ::apply {dir {
    namespace eval ::tcllib::ego [list ::source $dir/ego.tcl]
    package provide ego 0.1
}} $dir]

ego.tcl


namespace ensemble create
namespace export *

proc .method {_ name args} {
	if {![llength $args]} {
		lappend args $name
	}
	set args [linsert $args[set args {}] 1 $_]
	set map [namespace ensemble configure $_ -map]
	dict set map $name $args
	uplevel 1 [list ::namespace ensemble configure $_ -map $map]
	return
}
.method [namespace current] .method


My objections to that style are as follows:

  1. There is no marker at all that this script file implements a package.
  2. The only indication that the script implements a package at all is in the pkgIndex.tcl file. And many packagers elect to build their own pkgIndex.tcl file with specialized instructions for the local platform.
  3. An interpreter that sources that file without the package ifneeded script provided will run that script in an unknown namespace, most likely global. In other modules, for instance chan, his code defines procs named gets, puts and read which will cause no end of confusion if they were to replace the global commands of those names.
  4. There is no technical reason for this arrangement vs. the arrangment outlines in the Tcl Style Guide.
  5. This style causes problems with the Tcllib test suite as it is, because tests inside of modules expect to be able to explicitly load other modules via source.
  6. This style is utterly incompatible with being packaged as a tcl module file (.tm).

In particular I would like to add that none of the above reasons are:

  1. Because it breaks my system for building self-contained executables

My kit builder breaks when it encounters this code because it is far outside the norm of what a Tcl packager should expect to see.