【发布时间】:2019-12-21 22:53:50
【问题描述】:
我有一个代码,它由一个包含多个函数的文件组成,其中一些函数使用persistent 变量。为了使其正常工作,持久变量必须为空。
有记录的方法可以在多功能文件中clear持久变量,例如:
clear functionName % least destructive
clear functions % more destructive
clear all % most destructive
不幸的是,我不能保证用户在调用函数之前记得清除persistent变量,所以我正在探索在代码开头执行清除操作的方法。为了说明这个问题,请考虑以下示例:
function clearPersistent(methodId)
if ~nargin, methodId = 0; end
switch methodId
case 0
% do nothing
case 1
clear(mfilename);
case 2
eval(sprintf('clear %s', mfilename));
case 3
clear functions;
case 4
clear all;
end
subfunction();
subfunction();
end
function [] = subfunction()
persistent val
if isempty(val)
disp("val is empty");
val = 123;
else
disp("val is not empty");
end
end
第一次运行时,我们得到:
>> clearPersistent
val is empty
val is not empty
我希望此时再次运行该函数,任何非 0 输入都会导致 val 变量被清除,但可惜 - 情况并非如此。在设置val 之后,除非我们使用顶部 sn -p externally 中显示的替代方案之一,或者修改.m 文件,否则它会保持设置。
我的问题:是否可以从主函数体内清除子函数中的持久变量,如果可以,如何?
换句话说,我正在寻找一些可以在调用子函数之前放入clearPersistent 的代码,以便输出一致:
val is empty
val is not empty
附言
-
这是一个相关的过去问题(不涉及此特定用例):List/view/clear persistent variables in Matlab。
-
我知道重写代码以完全不使用
persistent变量的可能性(例如,通过传递数据、使用appdata、向所有子函数添加'clear'标志等)。 -
请注意,编辑函数的源代码并保存会隐式清除它(以及所有持久变量)。
-
我知道文档指出“
clear函数不会清除本地或嵌套函数中的持久变量。
问题的其他背景:
实际代码结构如下:
Main function (called once)
└ Global optimization solver (called once)
└ Objective function (called an unknown N≫1 times)
└ 1st function that uses persistents
└ 2nd function that uses persistents
如 cmets 中所述,一些变量被持久化的原因有几个:
- 松散耦合/SoC:目标函数不需要了解子函数的工作方式。
- 封装:它是一个实现细节。持久变量不需要存在于使用它们的函数范围之外(即没有其他人需要它们)。
- 性能:持久变量包含计算成本相当高的矩阵,但每次调用主函数时,此操作只需执行一次。
使用持久变量的一个(副作用?)效果是使整个代码有状态(具有两种状态:before 和 after 昂贵的计算)。最初的问题源于在调用 main 函数之间未正确重置状态,导致运行依赖于使用先前(因此无效)配置创建的状态。
可以通过计算主函数中的一次性值(目前仅解析用户提供的配置,调用求解器,最后存储/显示输出),然后将它们与用户配置一起传递来避免有状态进入目标函数,然后将它们传递给子函数。这种方法解决了状态清除问题,但会损害封装性并增加耦合性,进而可能会损害可维护性。
不幸的是,目标函数没有flag that says 'init' etc.,所以我们不知道它是在第 1st 次还是第 nth 次调用,没有跟踪这就是我们自己(AKA state)。
理想的解决方案应该有几个属性:
- 一次计算昂贵的数量。
- 无国籍。
- 不传递不相关的数据(即“需要知道基础”;各个函数工作区只包含他们需要的数据)。
【问题讨论】:
-
clear classes实际上是最具破坏性的,但它仍然不会清除锁定的项目。 -
乍一看,我相信解决方案超出了问题的范围。即没有一个好的解决方案最终不会变得不可维护,隐藏它的行为,不是很可测试,而且通常非常hacky。如果您为更高级别的问题提供更多范围,我们也许可以提供替代解决方案。
-
@LightCC 你说得对,我不清楚我到底为什么要问这个,替代解决方案更有意义。也许我出于问题的目的过度简化了我的问题,因此我将尝试添加更多上下文以确保完整性。
-
由于您对问题的更改改变了答案的含义和有用性,让我收回我的赞成票。
-
您是否考虑过使用类(面向对象编程)并将单例对象存储在全局持久数据中来访问它?然后你可以在课堂上做任何你想做的事情来存储昂贵数据的结果,存储状态,并在你想要的任何条件/方法调用上清除数据和状态......我才刚刚开始搞乱Matlab,所以不确定如何以您需要的方式最好地与全局存储交互。
标签: matlab global-variables state persistent-storage local-functions