TCL中声明常量的方法是什么?

What method is this of declaring constants in TCL?

我在别处读到可以使用关键字 set 在 TCL 中创建常量。但是,当我查看 math 包的源代码时,我发现数学常量的声明方式不同。请参阅下面的code

package provide math::constants 1.0.1

# namespace constants
#    Create a convenient namespace for the constants
#
namespace eval ::math::constants {
    #
    # List of constants and their description
    #
    variable constants {
        pi        3.14159265358979323846   "ratio of circle circumference and diameter"
        e         2.71828182845904523536   "base for natural logarithm"
        ln10      2.30258509299404568402   "natural logarithm of 10"
        phi       1.61803398874989484820   "golden ratio"
        gamma     0.57721566490153286061   "Euler's constant"
        sqrt2     1.41421356237309504880   "Square root of 2"
        thirdrt2  1.25992104989487316477   "One-third power of 2"
        sqrt3     1.73205080756887729533   "Square root of 3"
        radtodeg  57.2957795131            "Conversion from radians to degrees"
        degtorad  0.017453292519943        "Conversion from degrees to radians"
        onethird  1.0/3.0                  "One third (0.3333....)"
        twothirds 2.0/3.0                  "Two thirds (0.3333....)"
        onesixth  1.0/6.0                  "One sixth (0.1666....)"
        huge      [find_huge]              "(Approximately) largest number"
        tiny      [find_tiny]              "(Approximately) smallest number not equal zero"
        eps       [find_eps]               "Smallest number such that 1+eps != 1"
    }
    namespace export constants print-constants
}
  1. 变量常量”是字典吗?好像是这样。但是variable是什么关键字?
  2. 为什么我们需要 namespace eval 然后 namespace export?我的意思是,为什么不只说一次 namespace ::math::constants 并保留它呢?
  3. 为什么我们需要这一行 namespace export constants print-constants?
  4. 为什么不直接使用 TCL set 命令创建常量?
  5. 我们真的不能在 TCL 中拥有常量(就像 C 中的 const 关键字)并且一切都可以重新定义为我们想要的任何东西吗?这不会为这种语言带来安全问题吗?
  1. Is the "variable constants" a dictionary? It appears to be so. But what keyword is variable?

不是(或者是,但只是偶然)。它定义的每个事物在定义中都有三个,而字典中每个映射条目严格有两个词。

variable 命令记录在:https://www.tcl-lang.org/man/tcl8.6/TclCmd/variable.htm

  1. Why do we need the namespace eval and then namespace export as well? I mean why not just say namespace ::math::constants once and leave it at that?
  2. Why do we need this line namespace export constants print-constants?

namespace export 定义了哪些命令 是从名称space 中导出的,即哪些可以namespace import 由别处编辑。没有假设所有命令都被导出。没有假设 namespace 导出与其自身同名的命令。不导出变量(但可以实现类似的效果;在 namespaced 个变量之间很少这样做)。

如果您使用 namespace ensemble 中的默认值或者如果您继续使用 TclOO,这会改变 。那些 做出(记录在案!)默认假设。

变量和命令是完全不同的东西。它们使用不同的 space 名称(即,它们在每个名称space 中具有不同的散列值 table)并且不会混淆。 math::constants 包提供了一个命令来做额外的事情,但这只是包的一个特性,并不是什么通用的。

许多名称space从不导出任何命令。那完全没问题。始终可以通过完全限定名称访问命令和变量。

  1. Why not just create the constants using the TCL set command?

可以,在全局名space。按照惯例,泛型库会尽量将其留给 Tcl 本身(尽管 Tcl 也保留一些名称space,尤其是 ::tcl)和应用程序,即您的代码。

但是在 non-root 名称space 中,出于严重丑陋的原因,我认为最好将其视为错误,最好使用 variable 命令创建变量。从技术上讲,这不是一个错误,而是一个 非常 non-obvious 变量如何解析的结果,我非常讨厌它。 (我认为它会在 Tcl 9.0 出现时消失。)以另一种方式 可能 工作,但它可能不会,你真的不想要仅 可能 在生产中工作。当全局名称中存在同名的现有变量时会出现问题space…而且只是 UGH!

setvariable 之间在这方面的差异导致了 Tcl 自己的包中的许多错误。

  1. Is it true that we cannot actually have constants in TCL (like const keyword in C) and that everything can be redefined to whatever we want? Does this not create security issues for this langauge?

一般来说,这没有安全问题。原因是 several-fold:

  1. 值(不是变量)在他们的模型中是 immutable;如果某样东西有价值,它就不会从脚下变异出来。
  2. 您可以使用适当的轨迹来模拟常量,但这并不常见。毕竟,仍然可以 unset 变量并且不能真正被阻止;例如,如果正在删除包含名称space,它必须起作用。一旦可以删除,就不能保证是常量。
  3. Tcl 使用解释器作为其基本的安全边界,并且从子解释器到达其父解释器的能力受到极其严格的控制,主要是通过返回值或调用 cross-interpreter 别名命令(这大致就像做一个系统调用,除了轻量级得多)。不受信任的代码可以是 运行 在它不会造成损害的上下文中,但恰好具有您想要赋予它的额外功能(并且由您决定如何防止滥用)。

常量在其他语言中的主要用途是什么?好吧,有各种类型的枚举(在 Tcl 中,您可以使用项目的名称或名称列表,两者都不能重新映射到其他不合适的东西),然后有像您描述的那样的特殊常量。这些通常不是安全令牌,而是如果有人将 pi 设置为 3.0 那么他们只会得到错误的答案。就在他们身上!

Tcl 不会阻止您在自己的解释器中引起问题。你真的可以做一些事情,比如替换 whileforeach 等等(在某些情况下这样做很有用)。但如果你弄错了,你所做的就是给自己带来麻烦。我曾经决定为所有以它们执行的操作命名的按钮制作图标图像,然后短暂地想知道为什么每次调用 open 文件都停止工作。好吧。

但是一个解释器中的操作 不能 影响另一个解释器中发生的事情,除非另一个解释器允许(或者如果它是父解释器中的操作影响它的一个或多个子解释器) .这就是安全域障碍。不要在受信任的上下文中评估不受信任的代码。只是不要。