Code covered by the BSD License

# 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

functional_programming_bonus.m
```%% Bonus Examples
% Tucker McClure
% Copyright 2013 The MathWorks, Inc.

% If it doesn't work, try saying "please".

% Example:

%% Bonus 2: Anonymous Do-While
% In the examples, we didn't show how to create a do-while loop
% anonymously. Here it is.

dowhile = @(x0, cont, fcn, cleanup) recur(... % Make the recursion.
@(f, x) use(fcn(x), @(z) ...              %   Run the fcn, save as z.
iif(cont(z), @() f(f, z), ... %   Continue?
true,    cleanup(z))),... % Stop, clean up.
x0);                                      % Initial state

% Create a function to draw sets of numbers until it draws n positive
% numbers in a row.
draw_until_all_positive = @(n) dowhile([], ...               % No x0
@(x) any(x < 0), ...  % Until all >0
@(~) randn(1, n), ... %   Draw set
@(x) x);              % Return set

fprintf('Draw numbers until we get 5 positive numbers in a row.\n');
draw_until_all_positive(5)

%% Bonus 3: A Large Program
% This is probably not the world's best example of good programming
% practices, but it does serve to illustrate that entire programs *can* be
% built with anonymous functions (whether or not they *should* be built
% this way or whether this is the best way to do it are very different
% questions).
%
% This example uses most of the techniques developed in the
% functional_programming_examples (though it uses the .m versions instead
% of the anonymous versions), including |forloop|, |iif|, |last|, |use|,
% |recur|, |tern|, and |void|. Creating this example also served to prompt
% me to make functions that simplify programming this way.

% Set up the figure.
figure(1);
clf();
set(1, 'Color', 'k');
axis([-20 20 0 25], 'off');
set(gca(), 'Position', [0 0 1 1]);
hold('on');

% Create some constants.
nf = 6;       % Number of fireworks
np = 100;     % Number of particles per firework
n  = nf * np; % Total number of particles
dt = 1/24;    % Time step

% Create some fireworks.
create_fireworks = @() forloop([], nf, @(p,~) ...
use(2*randn, rand, @(x, y) ...
[p repmat([2*x, -5*y, 5*x, 20*y+30]', 1, np)]));

% Plot the fireworks.
random_color = @() 1./(1+exp(-20*(rand(1, 3)-0.4))); % It's a sigmoid fcn.
create_plot = @(x0) forloop([], nf, @(h,~) ...
[h plot(x0(1,:), x0(2,:), '.', 'Color', random_color())]);
limit = @(x) min(max(x, 0), 1);
update_plot = @(x, h, k) forloop([], nf, @(~,z) ...
void(@() set(h(z), 'XData', x(1, np*(z-1)+1:np*z), ...
'YData', x(2, np*(z-1)+1:np*z), ...
'Color', limit(1.03-1e-3*k) * get(h(z),'Color'))));

% Propagate the fireworks' particles. At k == 25, make them explode.
explode  = @(x) x + [zeros(2, n); 5*randn(2, n)];
Phi      = expm(dt*[0 0 1 0; 0 0 0 1; 0 0 -1 0; 0 0 0 -1]);
g        = repmat([0 -dt*9.81 0 -0.5*9.81*dt^2]', 1, n);
update_x = @(k, x) Phi * tern(k==25, @() explode(x), @() x) + g;

% Functions to change callback and show text.
set_callback = @(cb) void(@() set(gcf, 'WindowButtonDownFcn', cb));
show_text    = @() text(0, 1, 'Click for fireworks.', ...
'HorizontalAlignment', 'center', ...
'Color', 'w');

% Create the anonymous program.
fireworks = @() recur(@(self) {...                 % To reference itself.
set_callback([]), ...                          % Clear the callback.
void(@() delete(findobj('Type', 'text'))), ... % Delete the text.
use(create_fireworks(), @(x0) ...              % Create positions, x0.
use(create_plot(x0),    @(h) ...               % Plot, keep handle, h.
{forloop(x0, 100, @(x,k) ...                   % Loop from k=1:100.
last(update_plot(x,h,k), ...          %   Update plot.
void(@() pause(dt)), ...         %   Wait.
{update_x(k,x)})), ...           %   Update state.
void(@() delete(h))} ...                      % Delete fireworks.
)), ...                                        % (End of x0, h scope.)
show_text(), ...                               % Create text again.
set_callback(@(~, ~) self(self))});            % Restore callback.

% Execute the anonymous program, which will also attach 'fireworks' to the
% button click callback.
fireworks();
```