How to compose functions with more than one output/input

71 vues (au cours des 30 derniers jours)
Joan Vazquez
Joan Vazquez le 16 Juin 2019
Modifié(e) : Joan Vazquez le 20 Juin 2019
How can I define a function "composeFunctions" that takes two functions as an input and returns their composition as an output, when the functions to compose have more than one output/input?
For example:
function h = composeFunctions(f, g)
h = @(x) g(f(x));
end
works well with functions , such as:
function y = add1(x)
y = x+1;
end
function y = add2(x)
y = x+2;
end
h = composeFunctions(@add1, @add2)
% it works, h(5) returns g(f(5)) = 5 + 1 + 2 = 8, as expected
but I do not know what to do e.g. with functions , , such as:
function [y1, y2] = duplicate(x)
y1 = x;
y2 = x;
end
function y = addition(x1, x2)
y = x1 + x2;
end
h = composeFunctions(@duplicate, @addition)
% h(5) throws an error because duplicate does not pass two arguments to addition
Note 1 : this is a MWE, I want to better understand how to work with functions of functions, so I am not interested in built-in solutions like the compose function in the symbolic math toolbox.
Note 2: all functions are defined in their own .m file in the working directory, I am posting it like this for simplicity. A similar single input/output implementation is given here with anonymous functions.

Réponses (1)

Walter Roberson
Walter Roberson le 16 Juin 2019
In MATLAB, in every case where you have an expression of the form F(G(inputs)), it is not possible for F to capture all of the outputs of G. There is no work-around using expression syntax.
The closest you can get is to use a real function (not anonymous) F(@g, N, inputs) with
function result = F(fun, N, varargin)
[funout{1:N}] = fun(varargin{:});
result = some_operation_on(funout{:});
end
You could define something like,
function result = compose2_1(fun1, fun2, varargin)
[out2_1, out2_2] = fun2(varargin{:});
result = fun1(out2_1, out2_2);
end
and then
ad = @(x) compose2_1(@addition, @duplicate, x)
  1 commentaire
Joan Vazquez
Joan Vazquez le 20 Juin 2019
Modifié(e) : Joan Vazquez le 20 Juin 2019
Thanks, Walter!
Based on your answer, I wrote a function that works for the general case of dimensions
Then I wrapped your last line around another function, so the output is a function.
In case it helps anyone, here it goes:
function h = composeFunctions(f, g, varargin)
h = @(varargin) comp(f, g, varargin{:});
function [varargout] = comp(f, g, varargin)
N = nargout(f);
[funout{1:N}] = f(varargin{:});
M = nargout(g);
[varargout{1:M}] = g(funout{:});
end
end
The funny thing is that you need to specify some sort of "example input" as varargin in order to build the composite function h. I don´t see how to avoid this in Matlab! One could think of using nargin(f)...but the local function still needs to explicitely call f, so unless you know its domain, you cannot even build that "example input" inside composeFunctions. (e.g. f could be defined on strings, not numbers).
To give some context, I was self-studying Category Theory for Programmers (by Bartosz Milewski), which challenges the reader to program composition in his favourite language.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Numeric Types dans Help Center et File Exchange

Produits


Version

R2017b

Community Treasure Hunt

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

Start Hunting!

Translated by