# Currying in Matlab

As MATLAB has a hard maximum of 10 input arguments it's possible, but ugly, to implement a curry function in this manner:

%% turns a standard function into a curried one
%  if g has 3 input arguments then you can call:
%  h = curry(g)
%  h(1)(2)(3) == g(1, 2, 3)
%  Matlab doesn't like h(1)(2)(3), but in principle it works.
function fOut = curry(fIn)
fOut = fIn;

% can't curry a vararg function
if (nargin(fOut) < 0)
return
end

if (nargin(fOut) == 10)
fOut = @(bind)(curry(@(free1, free2, free3, free4, free5, free6, free7, free8, free9) (fIn(bind, free1, free2, free3, free4, free5, free6, free7, free8, free9))));
return
end

if (nargin(fOut) == 9)
fOut = @(bind)(curry(@(free1, free2, free3, free4, free5, free6, free7, free8) (fIn(bind, free1, free2, free3, free4, free5, free6, free7, free8))));
return
end

if (nargin(fOut) == 8)
fOut = @(bind)(curry(@(free1, free2, free3, free4, free5, free6, free7) (fIn(bind, free1, free2, free3, free4, free5, free6, free7))));
return
end

if (nargin(fOut) == 7)
fOut = @(bind)(curry(@(free1, free2, free3, free4, free5, free6) (fIn(bind, free1, free2, free3, free4, free5, free6))));
return
end

if (nargin(fOut) == 6)
fOut = @(bind)(curry(@(free1, free2, free3, free4, free5) (fIn(bind, free1, free2, free3, free4, free5))));
return
end

if (nargin(fOut) == 5)
fOut = @(bind)(curry(@(free1, free2, free3, free4) (fIn(bind, free1, free2, free3, free4))));
return
end

if (nargin(fOut) == 4)
fOut = @(bind)(curry(@(free1, free2, free3) (fIn(bind, free1, free2, free3))));
return
end

if (nargin(fOut) == 3)
fOut = @(bind)(curry(@(free1, free2) (fIn(bind, free1, free2))));
return
end

if (nargin(fOut) == 2)
fOut = @(bind)(curry(@(free1) (fIn(bind, free1))));
return
end

end


Is there a less horrible way to do this?

Initially, I tried using varargin which is how I assume the answer will look. Here's what I had at that time:

function fOut = curry(fIn)
fOut = fIn;

% can't curry a vararg function (nargin = -1) or a function with less than
% arity of 2
if (nargin(fOut) < 2)
return
end

fOut = @(bind)(curry(@(varargin)(fIn(bind, varargin{:}))));

end


The first thing I'd do would be to use a switch statement instead of the if statements. It cleans it up a bunch.

function fOut = curry(fIn)
fOut = fIn;
switch nargin(fOut)
case 5
fOut = @(bind)(curry(@(free1, free2, free3, free4) (fIn(bind, free1, free2, free3, free4))));
case 4
fOut = @(bind)(curry(@(free1, free2, free3) (fIn(bind, free1, free2, free3))));
case 3
fOut = @(bind)(curry(@(free1, free2) (fIn(bind, free1, free2))));
case 2
fOut = @(bind)(curry(@(free1) (fIn(bind, free1))));
otherwise
% Do nothing,
end
return


Also, more than 10 inputs are ok in Matlab:

f = @(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)cat(2,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);


Worked in R2008b and in R2012b:

f(1,2,3,4,5,6,7,8,9,0,1,2)
ans =
1   2   3   4   5   6   7   8   9   0   1   2


Of note, there is a curry function in the functional library on MatlabCentral. (I would have commented this, but I don't have the rep, yet...)

• Also: Why not use varargin? As long as the functional interface is consistent and always uses it, then wouldn't it work? I will have to look into currying a bit more to understand it better. Commented May 15, 2015 at 0:50
• currying simply takes a function and returns a series of functions that only take one argument. If you have a function f that takes 3 arguments, it transforms it into 3 chained functions (let's call the first g) that each take a single argument. So result = f(1, 2, 3); is equivalent to result = g(1)(2)(3) (the syntax of which Matlab doesn't seem to like, so technically h = g(1); then i = h(2); then result = i(3);) Commented May 15, 2015 at 1:46