Moving to Tcl 9.0

Moving to Tcl 9.0

Here is collected my humble experience of migrating scripts to Tcl 9.

The experience was mostly acquired at testing alited application.

There was used the stand-alone Tcl/Tk 9.0 executable (developer preview Tk builds with Tcl 9.0).


1. All scripts should be checked for ~ ("home directory"), at least for ~/

Tcl 9.0 doesn't expand "~" of file names, so if somewhere in application ~/ or ~user/ is used as the home directory, it should be replaced with some wildcard (e.g. %HOME/ or %USER/) or with a command (e.g. HomeDir).


2. Even more hard task is the replacements of NS::var with ::NS::var

In general, this task needs not only regexp searches but also scanning all scripts for possible usages of NS::var.

If such variables are used inside a namespace in the hope that they are ::NS::var, in Tcl 9.0 this will throw an error variable not found.

Quote: In Tcl 8 variable names that are not absolute, are resolved by looking first in the current namespace, and then in the global namespace. In Tcl 9 such variables are always interpreted as relative to the current namespace.

To find the issue points & to resolve the issue, some regular expressions may be used, such as the following ones:

\$\w+::               - e.g. for "$abc::def"
(^|[^:]){1}\m\w+::    - e.g. for "set abc::def"

To mitigate the task, alited provides excluding RE2 option.
For example, with RE:

(^|[^:]){7}\m\w+::
we search non-absolute names of variables and commands.

So that, excluding RE2 can be like these:

\s*proc\s+
\s*method\s+
(\[|\{|"|;)\s*\m\w+::
^\s*\m\w+::
to exclude declarations and calls of commands, because Tcl 9.0 modified only handling the non-absolute names of variables, while handling commands changed not.

To adapt my apps to Tcl 9.0, I've also used the following excluding RE2:

-command
-com
-tabnext
ttk::
\[list

For scanning all scripts for possible uses of NS::var, the alited's infobar is very helpful: just right-click on the infobar and choose Don't focus a text... item of the popup menu, and inside the infobar press Down key to scan and view all possible uses of NS::var, all of them are contextually viewed in the text frame. Also at the scanning, it's good to switch off the Files to Beginning option of alited's tabbar context menu.


3. Quote: "glob no longer raises an error if no files match"

Thus, catch*glob patterns should be changed, to insure against errors.

What errors? Example:

if {![catch {set baks [glob ${fname}*]}]} {
  foreach bak $baks {
    lappend bakdata [list [file mtime $bak] $bak]
  }
  set bakdata [lsort -decreasing $bakdata]
}

This code snippet works fine in all Tcl 8.6 versions. But in Tcl 9.0, if there aren't ${fname}* files, the baks list is empty and set bakdata [lsort -decreasing $bakdata] results in Tcl error (can't read "bakdata": no such variable).

So, the code should be changed to:

if {![catch {set baks [glob ${fname}*]}] && [llength $baks]} {
...
... to work both in Tcl 8.6 and Tcl 9.0.

Those potential errors can be rather hard to fix, if there are a lot of catch*glob patterns. They should be corrected manually depending on the specific use cases.

If catch is removed, the appropriate code patterns will work in Tcl 9.0 only.


4. Quote: "Deprecated trace subcommands variable, vdelete, vinfo have been removed"

For example,

trace variable varname w ...

should be replaced with

trace add variable varname write ...


5. Checking external Tcl/Tk tools for "package require Tk 8.6" and similar

Those commands should be package require Tk to test if the tools work fine with Tcl/Tk 9.0.

If some external package is included into your application with package require Tk 8.6, this command may be removed at all, as it's obviously run at starting your application.

The appropriate packages should be tested in both Tcl/Tk 9.0 and Tcl/Tk 8.6.


6. External packages

At adapting scripts to Tcl 9, you would appreciate the minimum use of external packages, if not avoiding them at all.

At any rate, using the external packages in subdirectories of your applications would save a lot of troubles with Tcl 9.0. In this case, you can manually adapt the packages to Tcl 9.0.

The appropriate adaptation is observed in the wiki page: Porting extensions to Tcl 9.


See also