在matlab中传递和保存匿名函数 [英] Passing and saving anonymous function in matlab

查看:26
本文介绍了在matlab中传递和保存匿名函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like a function (for example, a fit function) to return an anonymous function (usually stored in a struct) that I can save and use later. However, passing @func tends to pass a function pointer rather than the function itself. Is an inline function the only way to do this? I would like to avoid inline because it is extremely slow.

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

If that question is not clear, here is a sample of problematic code: I write a testFunc.m file in some PATH

    %testFunc.m
    function myfunc = testFunc()
        myfunc = @(x) x.^2;
    end

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

I then store the function in a struct. (I know this really should be an object!)

    >> 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,我将无法加载旧结构.相反,我收到错误:

If I then move myfile.mat or testFunc.m and load myfile.mat, I cannot load the old struct. Instead, I get the error:

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

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

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

I know there is a problem because, if I check functions

    >> functions(mystruct.func)

    ans = 

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

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

Is there some way to strip off the file workspace information? Are inline functions the only solution?

推荐答案

The Simple Case

如果您希望匿名的函数仅限于仅根据其输入参数定义(例如 inline 函数),并且您可以承诺在路径上保留一个函数,那么你可以制作净化"的匿名函数.

The Simple Case

If the functions you want to be anonymous are limited to being defined just in terms of their input parameters (like inline functions are), and you can commit to keeping one function on your path, then you can make "sanitized" anonymous functions.

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

因此,在您想要创建匿名函数的代码中,执行此操作.

So, in your code, where you want to make an anonymous function, do this.

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

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

As long as sanitized_anon_fcn.m stays on your path, you can delete testFunc2, and the saved function will continue to work. No special processing needed on save or load. Sanitized_anon_fcn basically works like inline but produces functions that are as fast as anonymous functions (because they are anonymous functions). The speed difference is about 10x in R2011b on my computer.

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

In the general case, where the functions might actually use variables from their workspace, things get trickier.

警告:这有点病态,我不赞成在生产代码中使用它.但作为语言如何工作的一个例子,我忍不住要发布它.

Caveat: This is a bit of a sick hack, and I do not endorse its use in production code. But as an example of how the language works, I can't resist posting it.

我认为你已经达到了 90%.但是您需要保留工作区信息而不是将其剥离,因为它可能有助于函数的操作.不要保存匿名函数句柄,而是获取您正在执行的 functions() 调用的输出并保存那个.

I think you're 90% there already. But you need to preserve the workspace info instead of stripping it off, because it may contribute to the operation of the function. Instead of saving the anonymous function handle, grab the output of that functions() call you're making and save that.

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

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

Then load it back. You'll still get the same warning, but now the warning applies only to function handles captured inside the workspace of your top-level anonymous function. If your function doesn't actually reference them (and it shouldn't), you can ignore the warning and it'll work.

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

然后将它传递给类似这个函数的东西,这将使您的匿名函数在新的工作空间中从死里复活,或多或少具有相同的工作空间值.

Then pass it to something like this function which will bring your anonymous function back from the dead in a new workspace with the same workspace values, more or less.

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!

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

Now, all the loaded anonymous functions will claim to be from this new file, but it shouldn't matter, because it's just the snapshotted state of the workspace, not closed-over variables, that is used by anonymous functions. And in the case where there were anonymous function handles in the workspace that actually were used by the computation, you'll get an appropriate error saying "Undefined function handle".

这是一个 hack,但也许您可以将其扩展为相当强大的东西.

This is a hack, but maybe you could take this and extend it in to something reasonably robust.

这篇关于在matlab中传递和保存匿名函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆