How to recursively reduce the function arguments

3 views (last 30 days)
Is there a way to create a function with one less argument dynamically? Basicly I'd like to find a way to do the following recursively or in a loop.
f4 = @(x1,x2,x3,x4) f5(x1, x2, x3, x4, 1);
f3 = @(x1,x2,x3) f4(x1, x2, x3, 1);
...
f1 = @(x1) f2(x1, 1);
r = f1(1)
function r = f5(x1, x2, x3, x4, x5)
r = x1 + x2 + x3 + x4 + x5
end
  2 Comments
David Hill
David Hill on 9 Nov 2021
Very confusing. An example would be helpful. It seems to me that r=f1=f2=f3=f4=f5=4+x1; which equals 5 in the example above (x1=1). Not sure what you are trying to do, but it is not wise to have all those variables.
Victoria Li
Victoria Li on 9 Nov 2021
Here is an example to calculate the double integral from 0 to 1 with composite simpson's rule. The function simpson2 takes a function argument. In the simpson2 function, I can only start the calculation when the function is a single variable. In the code below, I can transform the 2 variable function to a single variable function with given y values. I am looking for a more generic way to do this so it can handle integrals with more variables. To do this, it requires to transform the integral function with one less variable until it has only a single variable in each recursive iteration. The question above is simplified for achieving this.
f = @(x,y) (x.^2 + y.^2 );
a = 0;
b = 1;
m = 100;
integral = simpson2(a, b, m, f)
exact = integral2(f,a,b,a,b)
fprintf("Numerical Integral = %5.3f, Exact = %5.3f\n", integral, exact);
function integral = simpson2(a, b, m, fun)
% a, b: intregral boundary
% m: number of panels
% fun: function for integral
h = (b - a)/(2*m);
xi = a:h:b;
if nargin(fun) == 2
for i=1:length(xi)
fx = @(x) fun(x, xi(i)); % tranform to a single variable function with giver y varle
fx_val(i) = simpson2(a , b, m, fx);
end
elseif nargin(fun) == 1
fx_val = fun(xi);
fx_val(1);
else
fprintf("ERROR")
end
odd = double(sum(fx_val(3:2:end-1)));
even = double(sum(fx_val(2:2:end-1)));
integral = double(h/3 * (fx_val(1) + fx_val(end) + 4*(odd) + 2*(even)));
end

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 9 Nov 2021
It can be done with VARARGIN:
N = 5;
C = cell(1,N);
C{N} = @f5;
for k = N-1:-1:1
C{k} = @(varargin) C{k+1}(varargin{:},1);
end
C{1}(1)
ans = 5
function r = f5(x1, x2, x3, x4, x5)
r = x1 + x2 + x3 + x4 + x5;
end

More Answers (2)

Jan
Jan on 9 Nov 2021
This should work with str2func and eval.
This is such a cruel programming technique, that I recommend not to use it. Such meta-programming for creating code dynamically is hard to debug and Matlab's JIT acceleration cannot work. This can slow down the code by a factor 100 compared to some code, which avoid the dynamic creation of variables and functions.
  1 Comment
Adam Danz
Adam Danz on 9 Nov 2021
The function string could also be parsed to remove the penultimate input and then converted back to a function handle without using eval. But I still think there's a better approach.

Sign in to comment.


Adam Danz
Adam Danz on 9 Nov 2021
x1 = rand(1);
x2 = rand(1);
x3 = rand(1);
x4 = rand(1);
p = [x1, x2, x3, x4];
f5([p,1])
ans = 3.3148
p = [x1, x2, x3];
f5([p,1])
ans = 2.4283
p = [x1, x2];
f5([p,1])
ans = 1.8867
function f5(varargin)
sum([varargin{:}])
end

Categories

Find more on Mathematics in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!