matlab - 在matlab中传递和保存匿名函数

标签 matlab anonymous-function

我想要一个函数(例如,fit 函数)返回一个匿名函数(通常存储在 struct 中),我可以保存并在以后使用。但是,传递 @func 倾向于传递函数指针而不是函数本身。 inline 函数是执行此操作的唯一方法吗?我想避免 inline 因为它非常慢。

如果这个问题不清楚,这里有一个有问题的代码示例:我在一些 PATH

中写了一个 testFunc.m 文件
    %testFunc.m
    function myfunc = testFunc()
        myfunc = @(x) x.^2;
    end

然后我将函数存储在 struct 中。 (我知道这真的应该是一个对象!)

    >> mystruct = struct;
    >> mystruct.func = testFunc()
    >> mstruct.x = [1 2 3];
    >> save('myfile.mat','mystruct')
    >> mystruct.func(mystruct.x)

    ans = 

         1     4     9

如果我随后移动 myfile.mattestFunc.m 并加载 myfile.mat,我将无法加载旧结构。相反,我收到错误:

    >> cd 'otherdir'
    >> load('../myfile.mat')

    Warning: Could not find appropriate function on path
    loading function handle PATH/testFunc.m>@(x)x.^2 

我知道有问题,因为如果我检查函数

    >> functions(mystruct.func)

    ans = 

         function: '@(x)x.^2'
             type: 'anonymous'
             file: 'PATH/testFunc.m'
        workspace: {2x1 cell}

有没有办法去除文件工作区信息? inline 函数是唯一的解决方案吗?

最佳答案

简单案例

如果您希望匿名的函数仅限于根据它们的输入参数定义(例如 inline 函数),并且您可以 promise 在您的路径中保留一个函数,那么您可以制作“经过 sanitizer 的”匿名函数。

function out = sanitized_anon_fcn(str)
out = eval(str);
end

因此,在您的代码中,如果您想创建一个匿名函数,请执行此操作。

%testFunc2.m
function myfunc = testFunc2()
    myfunc = sanitized_anon_fcn('@(x) x.^2');
end

只要 sanitized_anon_fcn.m 留在你的路径上,你就可以删除 testFunc2,保存的函数将继续工作。保存或加载时无需特殊处理。 Sanitized_anon_fcn 基本上像 inline 一样工作,但生成的函数与匿名函数一样快(因为它们是匿名函数)。在我的计算机上,R2011b 的速度差异约为 10 倍。

一般情况

在一般情况下,函数实际上可能会使用其工作区中的变量,事情会变得更加棘手。

警告:这有点恶心,我不赞成在生产代码中使用它。但作为该语言如何工作的示例,我忍不住将其发布。

我认为您已经完成了 90%。但是您需要保留工作区信息而不是将其剥离,因为它可能有助于函数的运行。不要保存匿名函数句柄,而是获取您正在进行的 functions() 调用的输出并保存 that

fcn = testFunc();
fcn_info = functions(fcn);
save willbreak.mat fcn
save blah.mat fcn_info

然后加载回来。您仍然会收到相同的警告,但现在警告仅适用于在顶级匿名函数的工作区内捕获的函数句柄。如果您的函数实际上没有引用它们(而且它不应该),您可以忽略警告,它会起作用。

s0 = load('willbreak.mat')  % will warn and return unusable function
warning off MATLAB:dispatcher:UnresolvedFunctionHandle
s = load('blah.mat')  % will warn, but the first-level function will be usable
warning on MATLAB:dispatcher:UnresolvedFunctionHandle

然后将它传递给类似于此函数的函数,这将使您的匿名函数在新工作区中起死回生,新工作区具有相同的工作区值,或多或少。

function out = reconstruct_anon_fcn(s)

for iWks = 1:numel(s.workspace)
    wkspace = s.workspace{iWks};
    varnames = fieldnames(wkspace);
    for i = 1:numel(varnames)
        tmp = wkspace.(varnames{i});
        eval([varnames{i} ' = tmp;']);
    end
end

fcn_str = s.function;
fcn = eval(fcn_str);
out = fcn;
end

在我们的例子中:

fcn = reconstruct_anon_fcn(s.fcn_info)
fcn(2)   % and it works!

现在,所有加载的匿名函数都将声称来自这个新文件,但这无关紧要,因为匿名函数使用的只是工作区的快照状态,而不是封闭变量。如果工作区中存在计算实际使用的匿名函数句柄,您将收到一条相应的错误消息“未定义的函数句柄”。

这是一个 hack,但也许您可以将其扩展为相当稳健的东西。

关于matlab - 在matlab中传递和保存匿名函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9285725/

相关文章:

scala - Scala 中的匿名递归函数

matlab - MATLAB 中的循环缓冲区,**不**复制旧数据

c++ - 绘制我的 C++ 代码的中间结果的最佳工具是什么?

matlab - 使用 MATLAB 进行 REST API 交易

matlab - 如何从 Matlab 中的命令历史记录中检查命令的时间戳?

java - 匿名类如何传递本地参数?

matlab - 以编程方式保存MatLab中的所有脏文件

c# - 自调用匿名函数

javascript - 匿名函数作用域混淆

php - 在 PHP 5.3 之前的数组中关闭对象