gpt4 book ai didi

matlab - 从主函数中清除局部函数中的持久变量

转载 作者:太空宇宙 更新时间:2023-11-03 20:22:55 27 4
gpt4 key购买 nike

我有一个代码,它由一个包含多个函数的文件组成,其中一些函数使用 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 后,除非我们在 外部使用顶部代码段 中显示的替代方法之一,或者修改 .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
    正如评论中提到的,某些变量被持久化的原因有几个:
  • 松耦合/SoC:目标函数不需要知道子函数是如何工作的。
  • 封装:这是一个实现细节。持久变量不需要存在于使用它们的函数范围之外(即没有其他人需要它们)。
  • 性能:持久变量包含计算成本相当高的矩阵,但每次调用主函数时,此操作只需要发生一次。

  • 使用持久变量的一个(副作用?)效果是使整个代码有状态(有两种状态:在昂贵的计算之前和之后)。最初的问题源于这样一个事实,即在调用主函数之间没有正确重置状态,导致运行依赖于使用先前(因此无效)配置创建的状态。
    通过计算主函数中的一次性值(目前只解析用户提供的配置,调用求解器,最后存储/显示输出),然后将它们与用户配置一起传递到目标中,可以避免有状态函数,然后将它们传递给子函数。这种方法解决了状态清除问题,但会损害封装并增加耦合,这反过来可能会损害可维护性。
    不幸的是,目标函数没有 flag that says 'init' etc. ,所以我们不知道它是第 1 次还是第 n 次被调用,而我们自己没有跟踪这个(AKA 状态)。
    理想的解决方案具有以下几个特性:
  • 计算一次昂贵的数量。
  • 无国籍。
  • 不传递无关数据(即“需要知道基础”;单个函数工作区仅包含它们需要的数据)。
  • 最佳答案

    clear fnameclear functions 从内存中删除 M 文件。下次运行该函数时,它会再次从磁盘读取、解析并编译为字节码。因此,您减慢了函数的下一次执行。

    因此,从函数内部清除函数或子函数是行不通的。您正在运行该功能,您无法从内存中清除其文件。

    我的解决方案是向 subfunction 添加一个选项以清除其持久变量,如下所示:

    function clearPersistent()

    subfunction('clear');
    subfunction();
    subfunction();
    end

    function [] = subfunction(option)
    persistent val

    if nargin>0 && ischar(option) && strcmp(option,'clear')
    val = [];
    return
    end

    if isempty(val)
    disp("val is empty");
    val = 123;
    else
    disp("val is not empty");
    end

    end

    当然,您可以在作为 subfunction('init') 调用时初始化您的值。

    可能适用于您的用例的另一种解决方案是将 val 的计算与其使用分开。我会发现这比任何其他解决方案更容易阅读,并且性能也会更高。

    function main()
    val = computeval();
    subfunction(val);
    subfunction(val);
    end

    根据您的编辑,您可以将目标函数放在一个单独的文件中(在 private 子目录中)。您将能够对其进行 clear

    持久变量的替代方法是创建一个用户类,其中包含一个计算昂贵状态的构造函数,以及另一种计算目标函数的方法。这也可以是 classdef 子目录中的 private 文件。我认为这更好,因为您不需要记住调用 clear

    在这两种情况下,您不再拥有包含所有代码的单个文件。我认为您需要放弃这两个理想之一:要么破坏数据封装,要么将代码拆分为两个文件(代码封装?)。

    关于matlab - 从主函数中清除局部函数中的持久变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57510671/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com