I realize calling functions dynamically using feval is inefficient but it's quite convenient in my application and works well, except in the case of one function. I just can't see what is causing it. The function works fine when called in the usual way but raises the error when called with feval (last line in below):
x = 200;
[y_mean, y_sigma, y_int] = lin_model_predict(model, x, vars, params); % works fine
assert(round(y_mean, 4) == 139.7200);
assert(isequaln(y_sigma, nan));
assert(isequal(round(y_int, 4), [137.5938 141.8462]));
% Test again using feval
f_name = "lin_model_predict"; % this will later be set programatically
[y_mean, y_sigma, y_int] = feval(f_name, model, x, vars, params); % raises error
I include the function code below for reference:
function [y_mean, y_sigma, y_int] = lin_model_predict(model, x, vars, ...
params)
% [y_mean, y_sigma, x_int] = lin_model_predict(model, x, vars, params)
% Make predictions with a linear model of the form:
%
% power = a + b * load
%
% Make predictions using model
[y_mean, y_int] = predict(model, x, 'Alpha', vars.significance);
% TODO: Is there a need for sigma estimates?
y_sigma = nan(size(x));
end
Full error message:
Error using classreg.regr/CompactPredictor/feval
Too many output arguments.
Error in test_lin_models (line 46)
[y_mean, y_sigma, y_int] = feval(f_name, model, x, vars, params);
Matlab version: 2021b
Update
By replacing the last line with:
a = feval(f_name, model, x, vars, params);
I figured out that it is expecting one output argument.
By debugging this call I figured out that it is calling a method of a class in CompactPredictor.m located here:
/Applications/MATLAB_R2021b.app/toolbox/stats/classreg/+classreg/+regr/CompactPredictor.m
From the docstring of this function:
function yPred = feval(model,varargin)
%FEVAL Evaluate model as a function
% YPRED = FEVAL(M,X1,X2,...Xp) computes an array YPRED of predicted
% values from the regression model M using predictor values X1, X2, ...,
% Xp, where P is the number of predictors in M. Each X argument must be
% the same size, and must have the same type as the corresponding
% predictor variable. The size of the YPRED output is the same as the
% common size of the X inputs.
And in this case the model argument is now the string "lin_model_predict" which raises a new error Unrecognized method, property, or field 'NumPredictors' for class 'string'.
So it looks to me that the standard use of feval has been hijacked by this class method.
Not sure how to avoid this. Any ideas?
I decided to post the question on the Mathworks forum because it may require expert input:
Feel free to add answers there or here.
fevalyou want. You can try typingwhich fevalin your command window to further verify. Somehow this version got added to your path. Look intormpathto remove it - or maybe just relaunch MATLAB. You can also usebuiltinto call a particular version of a function but you shouldn’t have to do that here.fevalisn’t terrible (it’s not the same thing aseval), but you may find it slightly more efficient to specify the function name with a function handle rather than a character vector.which fevalreturns the correct version:built-in (/Applications/MATLAB_R2021b.app/toolbox/matlab/lang/feval). Butwhich feval(f_name, model, x, vars, params)returns/Applications/MATLAB_R2021b.app/toolbox/stats/classreg/+classreg/+regr/CompactPredictor.m % LinearModel method. I don't understand this since the first argument I am passing is a string, not the LinearModel.fevalexists that is explicitly overloaded for the class of any of the input arguments, then that overload is called. MATLAB doesn't look at the number of arguments to decide which function to call, only at the types of the input arguments you give when you call it. If there are multiple such functions (an overload for parameter #1, one for #2, etc) then it picks the one for the leftmost of these arguments.