How to recursively reduce the function arguments

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 Kommentare

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.
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

Melden Sie sich an, um zu kommentieren.

 Akzeptierte Antwort

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

1 Kommentar

Thanks Stephen for the help. Your solution works perfectly.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Jan
Jan am 9 Nov. 2021

0 Stimmen

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 Kommentar

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.

Melden Sie sich an, um zu kommentieren.

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

Kategorien

Mehr zu Loops and Conditional Statements finden Sie in Hilfe-Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by