Mathematica中的临时变量

5 投票
2 回答
1094 浏览
提问于 2025-04-16 06:40

我写了一个叫做MathOO的Mathematica包。简单来说,它让你在Mathematica中使用面向对象的编程,就像在Python中那样。想了解更多细节,可以看看这篇文章:Voofie/MathOO

MathOO:将Python风格的面向对象编程添加到Mathematica(1.0测试版发布)[Objectica的替代品]

我遇到的问题是,我希望有一个垃圾回收机制,这样用户在使用完对象后就不需要手动删除它。例如:

NewClass[Object1]
Object1.$init$[self_]:= Return[];

在上面的两行中,我定义了Object1作为一个新类,并且构造函数是一个空函数。如果你对Python熟悉的话,应该能看到它和__init__()的相似之处。

要创建一个Object1的实例,我这样做:

object1 = new[Object1][]

输出结果是:

Out: object$13

这里,object$13是一个临时变量。我希望的是,当没有任何地方再引用这个临时变量时,它应该自动被删除。但实际情况并没有按预期那样工作。我发现问题出在这里:

In:  y = Module[{x}, x[1] = 2; x]
Out: x$117

In:  FullDefinition[y]
Out: y = x$117
     Attributes[x$117] = {Temporary}
     x$117[1] = 2

因为y持有x$117的引用,所以x$117还没有被删除。现在我们通过把y的值设为1来删除这个引用:

In:  y = 1;

然而,x$117仍然存在:

In:  Definition[x$117]
Out: Attributes[x$117] = {Temporary}
     x$117[1] = 2

但我本来期待这个变量会被删除,因为它不再被引用。从Mathematica的手册中可以看到,它说:

临时符号在不再被引用时会被移除:

那么,这是不是Mathematica的一个bug?或者有没有什么解决方法?我使用的是Mathematica 7.0。非常感谢。

2 个回答

1

Mathematica 是一个字符串重写系统(底层的东西)(有点像)(其实不是)(但确实是)(总之……)这里的 DownValue “x$117[1] = 2” 可以看作是一个字符串重写规则。想象一下,这就像是一个关联数组里的一个条目。这个数组叫做 “x$117”,而这个条目是一个包含 {1,2} 的配对。只要这个数组里有条目,符号 “x$117” 就会被引用,Mathematica 就不会把它清理掉。

你最好的做法是在符号被销毁或者超出作用域时使用 Remove[]。因为 Clear[] 不够用,因为它不能消除与符号相关的剩余属性、消息或默认值,所以 Mathematica 仍然会保留对这个符号的引用。

2

Mathematica确实会在没有任何引用时清理掉Temporary变量。不过,你的x$117没有被清理掉有两个原因。

  1. 首先,Module使用的是词法作用域,这意味着模块里的变量是“局部”的,具体来说,它们会被赋予一个独特的名字,比如“var$modnum”,还有Temporary的属性。因为你给了x一个DownValue,所以在x被清理之前,必须先把这个DownValue清除掉。

  2. 其次,你的y被设置为临时变量x$...,而输出又被赋值给了Out[]。所以你还需要清理历史记录:Unprotect[In, Out]; Clear[In, Out]; Protect[In, Out];

这样你的Module示例就应该能正确地被清理了。


在使用你的MathOO包时(我昨天下载了,但还没试过),也许你可以把$HistoryLength设置为一个有限的数字。并建议用户抑制实例化的输出,比如object1 = new[Object1][];

撰写回答