Replacing variable names when using func2str of anonymous function
9 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
royk
am 24 Sep. 2019
Kommentiert: Guillaume
am 27 Sep. 2019
I have an anonymous function, say
f=@(x,y) x+y;
I can name the function using func2str:
func2str(f)
ans =
'@(x,y)x+y'
What if I want to get the function name with different names for the anonymous variables x,y. Say replacing x,y with the strings 'Small', 'Large' to yield:
'@(Small,Large)Small+Large'
This becomes more tricky if the function has x or y also as non-variables. say for the case of f(x) x+'x', the correct answer will be '@(Small)Small+'x''
15 Kommentare
James Tursa
am 25 Sep. 2019
The reordering issue can be catastrophic if you have something like y*x and it gets rewritten as x*y ... and you will be using it for matrix multiply or quaternion multiply which are non-commutative.
Walter Roberson
am 25 Sep. 2019
James has a good point. For use with the symbolic Toolbox, all of the variables need to represent scalar values. The work-around for that is to pass in a matrix of symbolic variables such as
sym('x', [4 4])
for a variable that is expected to be 4 x 4.
Unfortunately, picking back through the results of the expression to repackage the individual variables into an array can be a nuisance.
Akzeptierte Antwort
Guillaume
am 26 Sep. 2019
As I suggested, it's possible to do this with the undocumented mtree function:
function fstr = replacevar(fstr, vars, replacements)
%fstr: the code of an anomymous function (obtained with str2func). This code is only designed to work with anonymous functions.
%vars: a cell array of variable names to replace
%replacements: a cell array of replacement names
tree = mtree(fstr); %parse the function and get parse tree. Note that mtree is completely undocumented
fvars = tree.strings; %portion of the function that correspond to each parsed element. Includes variables and non-variables for now
[isrep, whichrep] = ismember(tree.strings, vars); %do any of the potential variable match one to be replace and which one?
toreplace = strcmp(tree.kinds, 'ANONID') & isrep(:); %replace elements that are ANONID (input variables of the anonymous function) and match a replaced variables
fvars = fvars(toreplace); %filter the list of potential variables to keep only the ones to be replaced
whichrep = replacements(whichrep(toreplace)); %get matching replacements
varloc = tree.position; %start position of variables in the strings (not sure it's the correct property but appears to be right)
varlength = cellfun(@numel, fvars); %couldn't find a length property in tree. get it from fvars instead
splits = [varloc(toreplace)'; varloc(toreplace)' + varlength]; %compute where to split fstr to isolate the variables
fsplit = mat2cell(fstr, 1, diff([1; splits(:); numel(fstr)+1])); %do the splitting every even element is a variable to replace
fsplit(2:2:end) = whichrep; %do the replacing
fstr = [fsplit{:}]; %and merge back
end
Of course, since mtree is completely undocumented, it's possible it breaks on some inputs and may stops working in future versions. Use at your own risk, but it appears to do the job correctly:
>> replacevar('f = @(x, yyz) strrep(x, ''x'', yyz)', {'x', 'yyz'}, {'str', 'reps'})
ans =
'f = @(str, reps) strrep(str, 'x', reps)'
2 Kommentare
Guillaume
am 27 Sep. 2019
Note that if the anonymous function contains another anonymous function definition using the same variable names, e.g.:
f = @(x, y) arrayfun(@(x, y) x+y, x, y);
Then the variables currently get replaced in both function. The code could be improved to not do this. This is left as an exercise to the reader, one that has time to work out how to get the information out of mtree. I believe it's probably not too complicated but I haven't got the time to work it out.
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Get Started with MATLAB finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!