Code covered by the BSD License

### Highlights from Functional Programming Constructs

5.0
5.0 | 7 ratings Rate this file 27 Downloads (last 30 days) File Size: 52.2 KB File ID: #39735

# Functional Programming Constructs

### Tucker McClure (view profile)

08 Jan 2013 (Updated )

A set of files for treating many operations, like "if", "for", and even "()", as functions.

### Editor's Notes:

This file was selected as MATLAB Central Pick of the Week

File Information
Description

This set of files enables working more easily with functions of functions for concise and powerful code.

A few highlights of this way of working:

* Map multiple inputs to multiple functions and assign multiple outputs with a single line.

* Use conditionals (like "if"), loops, and recursion in anonymous functions.

A document with derivations and examples of these functions is included. See the readme.txt. Also, each function contains a 'help' entry with examples.

This submission requires strong familiarity with function handles and anonymous functions. If those aren't familiar terms, check the documentation first!

Required Products MATLAB
MATLAB release MATLAB 8.0 (R2012b)
Other requirements Strong familiarity with function handles and anonymous functions
02 Mar 2015 Joerg

### Joerg (view profile)

Hi Tucker,

many thanks for the code. The "output" function is more flexibel if an optional argument is allowed:

function varargout = output(f, out_indices, varargin)

[outs{1:max(out_indices)}] = f(varargin{:});

varargout = outs(out_indices);

07 Nov 2013 Felipe G. Nievinski

### Felipe G. Nievinski (view profile)

I guess instead of a separate iiff.m function this could be a patch for the original iif.m (backwards compatible):

isodd = @(x) logical(mod(x,2));
if isodd(numel(varargin))
varargin(end:end+1) = [{true}, varargin(end)];
end

Comment only
07 Nov 2013 Felipe G. Nievinski

### Felipe G. Nievinski (view profile)

% inline if-else (special case of general inline if-elseif):
% (dispense with typing true as the penultimate input argument)
function varargout = iiff(varargin)
varargin(end:end+1) = [{true}, varargin(end)];
[varargout{1:nargout}] = iif(varargin{:});
end

Comment only
02 Sep 2013 Felipe

### Felipe (view profile)

output.m could reuse wrap.m, it seems:
function varargout = output(f, out_indices)
varargout = wrap(f, out_indices);
end

Comment only
11 Aug 2013 Felipe

### Felipe (view profile)

Thanks for taking the time to comment, Tucker.

Comment only
09 Aug 2013 Tucker McClure

### Tucker McClure (view profile)

Hi Felipe,

You bring up a great point. There's no way to tweak |curly| so that it will expand all of the contents of a cell array as arguments into a function (or at least I haven't figured out a good way), because this is handled higher up by MATLAB, which is only looking for the form |f(x{:})|. Since |f(curly(x, ':'))| doesn't fit this form, it just won't work (the call to |curly(x, ':')| will only return the first output when passed directly into a function.

*However*, there are still ways to do the desired thing, such as your use of the |use| command; they just don't involve using |curly|. For instance, if |f| returns a cell array, and we want to call |f|, expanding all items from its cell array output into a new function, |g|, like this:

>> g(f(){:}) % <- generates a syntax error

>> use(f(), @(x) g(x{:}));

This says, "Run f() and pass its output to the next argument, which is a function handle. That function can now use that output (which we've called |x| here) however we want." Because |use| allows one to run a command and "use" its output multiple times without saving it to a variable, it's quickly useful in complex anonymous functions.

If this is a common pattern, you can also define:

>> expand_into_fcn = @(f, x) f(x{:});

And now we can use this expansion function to emulate what MATLAB does natively. E.g., to expand all elements in a cell array returned by |f| into the |cat| function, it's really quite compact:

>> expand_into_fcn(@cat, f())

This is exactly the same as:

>> x = f();
>> cat(x{:})

Let's go a step further. Let's take multiple outputs from a function and pass those into a new function. We'll need |wrap| here. We'll take both outputs from |min([5 2 3])|, |wrap| them into a cell array, and expand that array into the |cat| function to concatenate them along dimension 1.

>> use(wrap(@() min([5 2 3]), 1:2), @(x) cat(1, x{:}))
ans =
2
2

Hope this helps!

Comment only
09 Aug 2013 Felipe

### Felipe (view profile)

I'm wondering if it's possible to harmonize the behavior of the curly.m function with that of the built-in {} in this case:
x = {'a' 'b'}, {x{:}}, {curly(x,':')}
x =
'a' 'b'
ans =
'a' 'b'
ans =
'a'
I don't think it's a problem with curly.m, as these anonymous functions also exhibit the same discord:
curlycolon = @(x) x{:}; {curlycolon(x)}
ans =
'a'
curlycolon = @(x) subsref(x, substruct('{}',{':'})); {curlycolon(x)}
ans =
'a'
I seems to be a specificity of the colon operator; from doc colon: "The colon notation can be used with a cell array to produce a comma-separated list. ... The comma-separated list syntax is valid inside () for function calls, [] for concatenation and function return arguments, and inside {} to produce a cell array."

I came across this problem trying to define this function:
subvec2ind = @(siz, subvecnum) use(num2cell(subvecnum), @(subveccell) sub2ind(siz, subveccell{:}));
subvec2ind([5 5 5], [1 2 3])
sub2ind([5 5 5], 1, 2, 3)

Comment only
07 Apr 2013 na ren

### na ren (view profile)

13 Mar 2013 Tucker McClure

### Tucker McClure (view profile)

Hey, thanks for all the good feedback everyone. I appreciate your taking the time to leave a rating!

Comment only
13 Mar 2013 Felipe G. Nievinski

### Felipe G. Nievinski (view profile)

06 Mar 2013 YONGSUNG

### YONGSUNG (view profile)

good

13 Feb 2013 Eric Sampson

### Eric Sampson (view profile)

Great work Tucker! :)

31 Jan 2013 Ian

### Ian (view profile)

This is an excellent introduction to functional programming in Matlab, thanks Tucker!!!

10 Jan 2013 Matthew