3
\$\begingroup\$

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
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 14, 2015 at 22:06
\$\endgroup\$
0

1 Answer 1

4
\$\begingroup\$

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

answered May 15, 2015 at 0:48
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented May 15, 2015 at 0:50
  • \$\begingroup\$ 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);) \$\endgroup\$ Commented May 15, 2015 at 1:46

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.