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

查看:440
本文介绍了在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?

推荐答案

简单案例

如果要匿名的功能仅限于仅根据其输入参数进行定义(例如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()调用的输出并保存 that .

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天全站免登陆