问题源于 Matlab 将 y 的值存储在匿名函数的本地工作区中,同时将符号 y 保留在函数定义的一部分中。
然后,正如您所指出的,func2str 函数转换定义而不用其值替换符号。
由于您的示例表明即使在从当前工作区中清除变量 y(值和符号)之后,您也希望函数句柄能够工作,所以我建议两条路径前进。
首先是使用y 的值创建带有str2func 的函数句柄,而不是让匿名函数持有它:
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 变体。
第二种方法也仅适用于示例中的简单变量存储。
嵌套句柄和闭包等将需要更复杂的算法来确定符号值并可能进行替换。