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).
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
).
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.
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 {[set baks [glob -nocomplain ${fname}*]] ne {}} { ...... 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.
For example,
trace variable varname w ...
should be replaced with
trace add variable varname write ...
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.
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.