动态模块作用域

DynamicModule 旨在成为一个词法作用域构造,也就是说 DynamicModule 变量将只限定那些在 DynamicModule 主体中按字面出现的变量的任何实例. 这与 Module 的工作方式类似. 例如,在输入中:
符号 xDynamicModule 限定作用域,并且它在主体中的实例被本地化并保持一个值,该值在生成的用户界面构造中被跟踪. 符号 y 是无作用域的,它指的是内核对 y 的当前值,可以随时设置,与用户界面结构无关.
无作用域的动态模块变量
DynamicModule 的词法作用域从未被严格执行过,DynamicModule 有可能对非词法的引用进行作用域的限定,这意味着它们不会以字面形式出现在 DynamicModule 的主体中.
违反词法作用域的 DynamicModule 用法示例:
在上面的例子中,Dynamic[x1]x 的词法作用域严格地由 DynamicModule 限定,但 f1[] 定义中的 x1 不是. 尽管如此,由 f1[] 生成的滑块显然改变了 DynamicModule 变量 x1 的值,而不是 x1 的全局内核实例.
这种用法模式在 Wolfram 语言中有效,但被认为是一种反模式,应该避免.
修复无作用域的动态模块变量
解决 DynamicModule 变量的作用域问题涉及重写代码,使变量的所有实例都出现在DynamicModule 变量的主体中. 在前面的示例中,可以通过将 Dynamic[x] 作为参数传递给 f[] 来修复问题.
修复词法作用域问题的版本:
在这种情况下,传递 Dynamic[x2] 而不是简单地传递 x2 很重要,因为 x2 的值必须保持未计算,直到它在表达式 Slider[Dynamic[x2]] 中完全表示.
如果需要直接访问变量而不是完整的 Dynamic 表达式,最好定义您的函数,使其接受一个封装在 Dynamic 中的变量. 在以下示例中,f3 定义了一个反转输入的滑块. f3 的函数模式中包含了 Dynamic 以便变量可以被隔离,并在定义中使用.
一个更复杂的示例,它定义 f3,接受 Dynamic 表达式:
检测无作用域的动态模块变量
系统选项 "DynamicModuleScopingEnabled" 可用于强制执行严格的词法作用域.
返回严格词法作用域的当前设置:
将设置更改为 True 并重新运算生成用户界面结构的代码,这允许您测试代码是否使用了不正确的作用域. 重新运行原始示例演示了一个不再与值连接的滑块.
使用严格的词法作用域运行的原始的、有缺陷的示例:
事实上,在 f4 中执行的滑块现在指的是全局内核变量 x4. 这一点可以通过在 DynamicModule 构造的内部和外部确认 Dynamic[x4] 的值来验证.
f4 现在指的是全局变量 x4
由于系统选项会影响系统中的所有代码,您可能需要将其恢复为其原始设置,以运行尚未更正作用域问题的代码.
将系统选项重置为其默认值: