操作Erlang中Tuples
的某些函数会导致操作后新元组的副本。在大多数情况下,程序不再对创建新元组的旧元组副本感兴趣。让我们看一个例子:
change(Position,Tuple1,NewValue) when size(Tuple1) > 10,Position < 10 -> NewTuple = erlang:setelement(Position, Tuple1, NewValue), %% at this point i don't want Tuple1 %% I want to destroy Tuple1 at this point ! %% how do i do it erlang:send(myprocess,NewTuple), ok.
在上面的例子中,我从现有的元组创建一个新的元组。如果我随后要这样做,我会想要破坏我自己的旧副本。我有一种感觉,编译器/运行时系统会自动执行此操作,但如果是这样的话,他们就不会给我们这样的函数,例如:erlang:garbage_collect/0
。我们确定他们意识到我们可能需要隐含地管理我们的内存,可能会使程序免于崩溃并找到通过代码的内存密集部分的方式。
我理解在erlang shell
中,有可能使用f/0, f/1
让它忘记变量(假设它们的意思是销毁变量)。但是,似乎我不能在我的模块/功能中使用它。我还怀疑在变量名称前面放置一个下划线可能会加速运行时系统的破坏,即在我的代码中写一些内容:_Tuple1
来销毁Tuple1
。总之,问题是,如果我随后将从现有的元组创建元组,并且在每一步我想立即销毁旧副本(我自己),我该怎么做? *注意* 据我所知,效率指南禁止此操作,但如果我别无选择.....
大家帮忙,你的解决方案是什么?感谢
答案 0 :(得分:8)
编译器在以下后很容易检测到:
NewTuple = erlang:setelement(Position, Tuple1, NewValue),
此处不再引用 Tuple1
,并将删除其链接。没有必要尝试帮助它做到这一点,我保证它比你或我做得更好。下次有垃圾收集,如果没有其他引用它然后它将被回收。实际上收集器不会“销毁旧副本”,而只是将数据标记为空闲,以便可以重复使用。没有办法明确地自己这样做,这是一件非常好的事情!如果它在正常处理之外进行,它将干扰正常的内存分配/垃圾收集。
更重要的是,这种显式内存管理是我们想要避免的,这就是为什么它都是自动完成的。动态内存错误都很容易制作,之后很难找到。例如,在这种情况下,你如何知道,我的意思是100%确定真的知道,这个元组在其他任何地方都没有被引用,所以可以自由地回收它?垃圾收集器知道。所以留给收藏家吧。严重。
调用erlang:garbage_collect/0
会稍早运行收集器,但很少需要明确地执行此操作。
答案 1 :(得分:1)
没有办法做到这一点。此时调用erlang:garbage_collect/0
不会破坏Tuple1
,因为它仍然可以从堆栈中访问。