4

MATLAB 将变量与匿名函数一起存储。这是文档中的一个示例,说明了它是如何工作的。

表达式中的变量

函数句柄不仅可以存储表达式,还可以存储表达式求值所需的变量。

例如,为需要系数 a、b 和 c 的匿名函数创建函数句柄。

a = 1.3;
b = .2;
c = 30;
parabola = @(x) a*x.^2 + b*x + c;

因为 a、b 和 c 在您创建抛物线时可用,所以函数句柄包括这些值。即使您清除变量,这些值也会保留在函数句柄中:

clear a b c
x = 1;
y = parabola(x)
y =
   31.5000

假设 ab 和 c 的值与函数一起存储,即使它是从 mat 文件保存和重新加载的。在实践中,我发现这些值不会持续存在,尤其是在编辑最初创建函数的代码时。

有没有办法根据变量的数值定义函数句柄?我想要某种形式的东西

>> a = 1.3;
>> b = .2;
>> c = 30;
>> parabola = @(x) a*x.^2 + b*x + c

parabola = @(x) a*x.^2+b*x+c

>> parabola2 = forceEval(parabola)

parabola2 = @(x) 1.3*x.^2+.2x+30

编辑:也许我的问题出在文件关联上,但是当我编辑最初定义匿名函数的文件时,出现如下错误:

无法在 C: 中找到函数 @(ydata)nr/(na*dt)*normpdf(ydata,mu(j),s(j))./normpdf(ydata,mu_a(j),s_a(j))。 ..\m文件名.m。(我已将我的 mfile 的名称更改为 mfilename)

我通常对这类东西的解决方案是使用 func2str() 来删除文件依赖项,但这也会删除包括参数值在内的工作区信息。所以我想强制所有参数在函数定义中采用它们的数值。

4

3 回答 3

8

这些值存储在函数中。正如我之前在不同的答案中所展示的那样,您可以使用以下functions命令进行检查:

>> a = 1.3; b = .2; c = 30;
>> parabola = @(x) a*x.^2 + b*x + c;
>> x = 1;
>> y = parabola(x)
y =
         31.5
>> clear a b c
>> y = parabola(x)
y =
         31.5
>> fi = functions(parabola)
fi = 
     function: '@(x)a*x.^2+b*x+c'
         type: 'anonymous'
         file: ''
    workspace: {[1x1 struct]}
>> fi.workspace{1}
ans = 
    a: 1.3
    b: 0.2
    c: 30

即使您将句柄保存到磁盘:

>> save parabolaFun.mat parabola
>> clear parabola a b c
>> load parabolaFun.mat parabola
>> y = parabola(x)
y =
         31.5
>> fi = functions(parabola)
fi = 
     function: '@(x)a*x.^2+b*x+c'
         type: 'anonymous'
         file: ''
    workspace: {[1x1 struct]}
>> fi.workspace{1}
ans = 
    a: 1.3
    b: 0.2
    c: 30

您可以像这样简化抛物线手柄的创建:

function p = makeParabola(a,b,c)

p = @(x) a*x.^2 + b*x + c;

end

一些警告

您可以使用 MATLAB® 保存和加载函数在 MAT 文件中保存和加载函数句柄。如果您加载在早期 MATLAB 会话中保存的函数句柄,以下情况可能会导致意外行为:

  • 定义函数的任何文件都已被移动,因此不再存在于句柄中存储的路径上。
  • 您将函数句柄加载到与保存它的环境不同的环境中。例如,函数的源不存在或位于与保存句柄的系统不同的文件夹中。

在这两种情况下,函数句柄现在都无效,因为它不再与任何现有函数代码相关联。尽管句柄无效,但 MATLAB 仍然成功执行加载并且不显示警告。但是,尝试调用句柄会导致错误。

因此,如果您从文件支持的函数(不是脚本,没关系)创建句柄,然后修改或删除文件,则句柄将变为无效。

于 2014-11-07T21:06:07.410 回答
3

匿名函数捕获表达式中涉及的所有变量的值。如果您想查看捕获的环境工作区,请使用functions@chappjc在他的回答中显示

现在你必须小心匿名函数中使用的变量类型(想想值类型与句柄类型)。

所有本机类型(数字、逻辑、结构、单元格等)都是按值而不是按引用捕获的。例子:

x = magic(4);
f = @() x;    % captures matrix x

x(1) = 1      % modify x
xx = f()      % change not reflected here

将其与使用句柄类类型(例如containers.Map)进行比较:

x = containers.Map('KeyType','char', 'ValueType','double');
f = @() x;        % captures handle-class object x

x('1') = 1;       % modify map
keys(x)           % changed
keys(f())         % also changed!

f() == x          % compare handle equality, evaluates to true
于 2014-11-07T22:24:39.357 回答
1
a = 1.3, b = 0.2, c = 30;
parabola = eval(['@(x) ', num2str(a), '*x^2 + ', num2str(b), '*x + ', num2str(c)]);
于 2014-11-07T19:49:19.513 回答