如果将函数句柄转换为字符串并使用func2str和str2func函数再次返回,则创建时最初存储在函数句柄中的任何变量及其值都将丢失。
有没有办法克服这个问题?
像
y = 1;
fun = @(x) x + y
fun_str = func2str(fun);
clear y
fun = eval(fun_str);
result = fun(12); % This doesn't work
具体我有一个测量方法,创建一些数据,然后在fminsearch
的帮助下拟合对齐过程的某些自定义函数。我现在想存储所有数据以供将来分析。
由于Data通常比代码存活的时间更长,所以我想让它独立于任何源文件。这就是我将函数句柄转换为字符串的原因。在字符串中,只允许调用matlab builtin
个函数。
现在我可以做的当然是在示例中存储y
。但我想知道是否有一个更优雅的解决方案,我不需要这样做。
答案 0 :(得分:1)
问题源于Matlab将y
的值存储在匿名函数本地的工作空间中,同时保持符号y
成为函数定义的一部分。
然后,如您所示,func2str
函数转换定义而不用其值替换符号。
由于您的示例表明即使在清除当前工作空间中的变量y
(值和符号)之后您仍希望函数句柄工作,我建议前进两条路径。
第一种是使用str2func
创建带有y
的函数句柄,而不是让匿名函数保留它:
fun = str2func(['@(x) x + ',num2str(y)]);
另一种是编写func2str
的变体,在将函数转换为字符串后执行值替换。
functions
函数可用于获取匿名函数的工作空间,一些正则表达式可用于用文字替换符号。
这是一个最小的工作示例:
function str = func2strrep(fun)
% Grab workspace information
info = functions(fun);
workspace = info.workspace{1};
symbols = fieldnames(workspace);
% Initialize string
str = func2str(fun);
% Replace workspace variables with numeric literals
if not(isempty(symbols))
seps = '[\s\+\-\*\/\\\^\:\=\>\<]';
expr = @(s) ['(',seps,'{1})',s,'(',seps,'{1})'];
for k = 1:numel(symbols)
symbol = symbols{k};
value = num2str(workspace.(symbol));
% Check end of string
str = regexprep(str,['(',seps,'{1})',symbol,'$'],['$1',value]);
% Check bulk
stro = regexprep(str,expr(symbol),['$1',value,'$2']);
%
% Put in loop for repeated replacement since
% 'all' is not working as I thought it would.
while not(strcmp(stro,str))
str = stro;
stro = regexprep(str,expr(symbol),['$1',value,'$2']);
end
end
end
end
我对正则表达式没有天赋,所以替换方法可能需要一些调整(特别是因为regexprep
并没有取代我认为重复符号的所有匹配项)。
但是,这首先产生
>> y = 1;
>> z = 2;
>> yy = 3;
>> f = @(x) x + y + y + z + yy;
>> func2strrep(f)
ans =
@(x)x+1+1+2+3
这两种方法都依赖num2str
,因此只对标量值有用。
对于向量值,需要以字符串形式生成有效数组文字的num2str
变体才能使该方法起作用。
第二种方法也仅适用于示例中的简单变量存储。 嵌套的句柄和闭包等将需要更复杂的算法来确定符号值并可能替换。