http://www.purl.org/tcl/home/man/tcl8.4/TclCmd/package.htm See also [A simple package example]. ---- In response to a question about finding out versions of Tcl or Expect, [Donald Porter] writes: brentnye wrote: > There is a tcl command to find the version of tcl, i.e. > info tclversion Ick. Don't use that. And don't use the even worse $::tcl_version. Use [[package provide Tcl]]. ''([RS] uses most often "[info] pa" for the added detail)''. Several people have asked why I recommend [[package provide Tcl]] rather than [[package require Tcl]]. In the particular example of the Tcl package, it really doesn't matter, because the Tcl package is (practically) always provided. However, I wanted the example to generalize cleanly to other packages. [[package provide foo]] and [[package require foo]] differ in how they react when no ''foo'' package is currently in the interpreter. [[package provide foo]] returns an empty string, indicating no version of ''foo'' is provided. [[package require foo]], however, tries to go find the package ''foo'' and bring it into the interpreter. This is no longer introspection, but an action. Also, if [[package require foo]] fails to find ''foo'' among the installed packages, it will raise an error. The better choice for simple introspection is [[package provide foo]]. To add yet another wrinkle, [[package present foo]] occupies a middle ground. Unlike [[package require foo]], it will not attempt to load ''foo'', but like [[package require foo]], it will raise an error if no package ''foo'' is provided in the interp. I still prefer [[package provide foo]] for introspection because I don't have to [[catch]] it. (Although I do have to be careful about passing its return value to another command expecting a version number.) ---- How would one find the '''source to the package''' one is using? [Don Porter] offers namespace eval ::myIcons { # ... variable home [file join [pwd] [file dirname [info script]]] # ... } # ... proc ::myIcons::getPath {} { variable home return $home } '''DGP''' -- Hmmmm... since someone bothered to record that advice for Wiki posterity, I should add that this is nothing more than an updated version of the advice found in library(n) and tclvars(n) that each package should define a global variable ''${package}_library'' analogous to ''tcl_library'' and ''tk_library'' storing the directory in which that package is installed. That original advice came before [namespace], back in the bad old days when the only persistent variables that could be defined were global variables. (``Persistent'' in the sense that they live longer than the execution of one [proc].) Nowadays, we clearly shouldn't be defining global variables when a namespace variable will do. Also, I've moved away from a variable named ''library'' because I find that word is used to just mean way too many different things. It's just too confusing. ---- [[Is there no succinct reference that explains the crucial role of pkgIndex.tcl?!? [CL] will return to this, if no one else does.]] '''DGP''' --- The man page for pkg_mkIndex, http://www.purl.org/tcl/home/man/tcl8.4/TclCmd/pkgMkIndex.htm covers the basics in the HOW IT WORKS section. [[Good point.]] It's crucial that package authors understand pkgIndex.tcl as a keyword in package preparation. '''DGP''' --- For now, yes, but stay tuned for better ideas. We don't want to be chained to pkgIndex.tcl files forever. See also [pkg_mkIndex pitfalls]. ---- [[One summary statement: package use currently requires comprehension of pkgIndex.tcl (see [Magic names]).]] ---- Don Porter advises, "Anyone writing packages should read [William Duquette]'s tutorial on 'Namespaces and Packages' [http://www.wjduquette.com/tcl/namespaces.html] first." Also, note that Don made a presentation on how package unknown works and you can find the slides at [http://math.nist.gov/~DPorter/tcltk/oscon/]. A current version of the work appears at http://math.nist.gov/~DPorter/tcltk/package/ . ---- [[Distinguish package users and authors.]] ---- Don writes, "The main weakness is that the [[package]] system does not keep track of what the interdependencies are. We get "can't find package foo" instead of 'could not load package foo 1.3 because it depends on bar 2.1, and that is not installed'." CL agrees with this, and complains that package authorship is clumsy and error-prone. Perhaps more on this subject will appear in October 2001. ---- '''package names''' will only deliver all available packages if it has searched all package indices before. To force this, do a dummy ''package require'' before: catch {package require nonexistentName} package names '''[DGP]''' - To be more precise, [[package names]] returns a list of all the package names that are already known to the [[package]] command. That is not the same as all the names that could become known by operation of the [[package unknown]] callback. The default [[package unknown]] callback is [[tclPkgUnknown]] and it is that default callback that exhibits the behavior described above -- after one run, all installed package names are known. The [[package unknown]] interface does not require that behavior, and other callbacks may not (IMHO, should not) implement it. ---- [Using Tk as a loadable package] ---- [JCW] was once heard to conclude, "Package require is a contract to make a certain API available, not a procedural-call-with-side-effects in disguise - IMNSHO." ---- See also '''On Namespaces And Packages''' [http://www.wjduquette.com/tcl/namespaces.html] and '''Programmation modulaire en Tcl/Tk''' [http://www.larochelle-innovation.com/tcltk/pages/librairie.tml]. ---- '''List of currently loaded packages:''' proc packages {} { # returns the list of presently loaded packages set res {} foreach i [package names] { if {[string length [package provide $i]]} { lappend res $i } } set res } ;# RS ---- [Tcl syntax help] - [Category Command]