Mathematica中的临时变量
我写了一个叫做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 个回答
Mathematica 是一个字符串重写系统(底层的东西)(有点像)(其实不是)(但确实是)(总之……)这里的 DownValue “x$117[1] = 2” 可以看作是一个字符串重写规则。想象一下,这就像是一个关联数组里的一个条目。这个数组叫做 “x$117”,而这个条目是一个包含 {1,2} 的配对。只要这个数组里有条目,符号 “x$117” 就会被引用,Mathematica 就不会把它清理掉。
你最好的做法是在符号被销毁或者超出作用域时使用 Remove[]。因为 Clear[] 不够用,因为它不能消除与符号相关的剩余属性、消息或默认值,所以 Mathematica 仍然会保留对这个符号的引用。
Mathematica确实会在没有任何引用时清理掉Temporary
变量。不过,你的x$117没有被清理掉有两个原因。
首先,
Module
使用的是词法作用域,这意味着模块里的变量是“局部”的,具体来说,它们会被赋予一个独特的名字,比如“var$modnum”,还有Temporary
的属性。因为你给了x
一个DownValue
,所以在x
被清理之前,必须先把这个DownValue
清除掉。其次,你的
y
被设置为临时变量x$...
,而输出又被赋值给了Out[]
。所以你还需要清理历史记录:Unprotect[In, Out]; Clear[In, Out]; Protect[In, Out];
。
这样你的Module
示例就应该能正确地被清理了。
在使用你的MathOO包时(我昨天下载了,但还没试过),也许你可以把$HistoryLength
设置为一个有限的数字。并建议用户抑制实例化的输出,比如object1 = new[Object1][];