ひょんな事からTcl 8.6と9.0の些細(?)な違いにハマりました。
Tcllibのftpdを使おうとしたところ、Tcl 8.6ではpackage requireに成功するのに、Tcl 9.0ではエラーになりました。
% package require ftpd
1.4.1
% package require ftpd
can't read "tcl_platform(user)": no such variable
実行環境はMagicsplatからダウンロードした以下のインストーラで導入したものですが、
- Tcl 8.6: tcl-8.6.16-installer-1.16.1-x64.msi
- Tcl 9.0: tcl-9.0.2-installer-2.0.4-x64.msi
どちらに入っているtcllib ftpdも1.4.1で同じファイルでした。
9.0でエラーにっている箇所はftpd.tclの冒頭の
namespace eval ::ftpd {
:
variable contact
if {![info exists contact]} {
global tcl_platform
set contact "$tcl_platform(user)@[info hostname]"
}
:
という部分なのですが、Tcl 8.6ではglobalが効いているのに、Tcl 9.0では効いていない事がわかりました。
Tcl 8.6でも9.0でもglobalのヘルプには
This command has no effect unless executed in the context of a proc body.
と書かれていますが、Tcl 8.6ではヘルプに反してnamespace evalでもglobalが効いてしまっていたのが、Tcl 9.0ではバグフィックスされちゃったということですね。
Tcl 9.0のリリースノートを確認すると、ちゃんと載ってました。でもこれ見ただけで影響範囲を理解するのは難しい気がします。
Important Incompatibilities in Tcl 9.0
・Namespace varname resolution: Current namespace, not global.
:
Notable incompatibilities
・Unqualified varnames resolved in current namespace, not global. Note that in almost all cases where this causes a change, the change is actually the removal of a latent bug
重要な非互換性とは認めつつも「ちゃんとヘルプ読んで使ってりゃ問題ないやろがぃ」とか言われてるみたいで、いい気はしないですね。実際、ヘルプと実挙動が違ったら、「ヘルプの更新が遅れてるのかな?」と思う方が一般的じゃないでしょうか。
一応、tcllibの開発元に指摘をしておきましたが、そっちのバグフィックスを待たずにTcl 9.0でftpdを使いたい場合は、以下のようにすればOKです。
% namespace eval ::ftpd {variable contact;set contact "$::tcl_platform(user)@[info hostname]"}
% package require ftpd