hhh*_*hhh 2 matlab nested anonymous-function
我有一个存储匿名函数的文件funcs.m.它们必须可以被目录中的文件使用.目前,我使用匿名函数,以便我funcs.m在不同的文件中执行该文件,但我认为这是一种错误的做事方式.其他函数如main.m及其嵌套函数nest.m需要使用funcs.m中的匿名函数.我认为路径不会解决这个问题,因为文件在同一个文件夹中.基本上我可以通过将匿名函数复制粘贴到每个文件来解决这个问题,但代码闻起来如此:
有没有办法在Matlab中重用具有anon函数的funcs.m?
例
的main.m
Run Code Online (Sandbox Code Playgroud)function main funcs; % loads the anonymous functions nest(par1,...,parN) endnest.m
Run Code Online (Sandbox Code Playgroud)function nest(par1,...,parN) funcs; %ERRR: This fires err, why? Look: this was sourced already in main.m! function neededOnlyHere(par100) bq(q,A) %This needs the functions of the funcs end neededOnlyHere(somePar) %ERR to use the anon funcs from funcs end函数main.m和nest.m使用此函数funcs.m具有匿名函数
Run Code Online (Sandbox Code Playgroud)bq=@(q,A) q*A; %Bolded q I=@(ii,jj,A) find(A(ii,:)==1 & A(jj,:)==0); AiNotj=zeros(1,Ncut); ...错误
Run Code Online (Sandbox Code Playgroud)Attempt to add "bq" to a static workspace. See MATLAB Programming, Restrictions on Assigning to Variables for details. Error in funcs (line 10) bq=@(q,A) q*A; %Bolded q
调用它时会出现错误,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
Run Code Online (Sandbox Code Playgroud)
您可以import myfuncs.*从命令行执行此操作以使它们以交互方式可用.
这可能就是Matlab本身希望你组织这样的相关函数集群,这将是我的第一个方法.这是最不"臭"恕我直言.如果你真的希望能够在单个文件中编辑它们,就像funcs.m方便一样,你可以在Perl中编写一些代码munger或者解析funcs.m的任何代码,并将它们作为预处理步骤输出为等效的单独函数.(我认为你不能在像这样的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);
Run Code Online (Sandbox Code Playgroud)
为此,你必须在所有函数引用前加上你持有它们的结构名称.不知道这对你来说有多大.
function nest(par1,...,parN)
fs = funcs;
function neededOnlyHere(par100)
fs.bq(q,A) %This needs the functions of the funcs
end
Run Code Online (Sandbox Code Playgroud)
要使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
Run Code Online (Sandbox Code Playgroud)
这会有点痛苦,因为每当添加新的函数名时,您都必须重新编辑使用func的每个文件.您至少可以编写一个perl脚本来自动生成该行代码,方法是解析funcs.m并输出"[bg,I,AiNotj,...] = deal();" 使用它找到的所有功能,您只需将其复制到您的代码中即可.
另一种方法是让func实际返回其输出列表中的所有函数.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
Run Code Online (Sandbox Code Playgroud)