为什么会破
调用它时会出现错误,nest.m
因为嵌套函数使其封闭函数的工作区成为“静态工作区”;也就是说,不能通过 、 或其他“动态”技术添加变量eval()
名assignin()
;仅允许在该函数的文本中明确分配的变量。评估脚本以定义局部变量 - 这是您在调用时所做的funcs.m
- 是“动态的”,因此在具有嵌套函数的函数中被禁止。它之所以起作用,main.m
是因为 main 没有嵌套函数,因此是一个“动态”工作区。
有几种方法可以将其更改为使用静态工作区和嵌套函数。首先要问的是你是否真的需要让它们成为匿名函数?
改用包函数
如果您不需要它们本身是匿名函数,只需将它们分解并将每个作为常规函数放在自己的.m
文件中即可;例如bg.m
, I.m
, AiNotj.m
, 等等。然后它们都可用于该目录中的所有其他功能。
如果这变成了一堆文件,或者如果你想限定它们的范围,并且可能只让它们对真正需要它们的选定函数可用(即,当前调用的函数funcs()
),那么你可以将它们放在一个包中。创建一个名为的子目录+myfuncs
并将所有的小函数文件移到那里;例如+myfuncs/bq.m
, +myfuncs/I.m
, +myfuncs/AiNotj.m
. (+
前缀告诉 Matlab 目录是一个包。)然后您可以将它们全部拉入您的函数范围,import myfuncs.*
直接替换您当前调用funcs()
的 .
function nest(par1,...,parN)
import myfuncs.*;
function neededOnlyHere(par100)
bq(q,A) % This will work, resolving to myfuncs.bq
end
您也可以import myfuncs.*
从命令行执行,以使它们也以交互方式可用。
这可能是 Matlab 本身希望您像这样组织相关函数集群的方式,这将是我的第一种方法。这是最不“臭”的恕我直言。如果您真的希望能够在单个文件中编辑它们,就像funcs.m
为了方便一样,您可以在 Perl 或任何解析 funcs.m 的东西中编写一个小代码 munger,并将它们作为预处理步骤作为等效的单个函数输出。(我认为你不能像这样在 M 文件中定义多个顶级函数有点令人遗憾,但是哦。)
如果你真的需要使用匿名函数,有一些解决方法。
在结构中传递函数
您可以更改 funcs() 函数以实际返回所有这些匿名函数的结构,使用字段名称而不是局部变量名称。
function out = funcs
out.bq=@(q,A) q*A; %Bolded q
out.I=@(ii,jj,A) find(A(ii,:)==1 & A(jj,:)==0);
out.AiNotj=zeros(1,Ncut);
为此,您必须在所有函数引用的前面加上您保存它们的结构名称。不知道这对您来说有多大意义。
function nest(par1,...,parN)
fs = funcs;
function neededOnlyHere(par100)
fs.bq(q,A) %This needs the functions of the funcs
end
预分配变量
要让 funcs() 按原样工作,您可以使用您要使用的所有函数名称静态预分配变量,因此 Matlab 解析器将它们识别为静态分配的变量。然后当您调用 funcs() 时,它将重新分配现有变量的值,这在动态工作区中是允许的。
function nest(par1,...,parN)
[bq, I, AiNotj] = deal(); % Preallocate all names from funcs
funcs;
function neededOnlyHere(par100)
bq(q,A) %This needs the functions of the funcs
end
这会有点痛苦,因为每当添加新的函数名称时,您都必须重新编辑每个使用 funcs 的文件。您至少可以编写一个小 perl 脚本,通过解析funcs.m
和输出“[bg, I, AiNotj,...] = deal();”来自动生成那行代码。使用它找到的所有功能,您只需将其复制到您的代码中即可。
另一种方法是让 funcs 实际上返回其输出列表中的所有函数。funcs.m
只要您不删除或更改现有匿名函数的顺序,这将有利于即使您向 中添加新函数也能继续工作。
function [bg,I,AiNotj] = funcs()
bg = ...
I = ...
% And then in the calling functions:
[bg,I,AiNotj] = funcs(); % which you can copy and paste from funcs.m's header