Loren on the Art of MATLAB

Thoughts about Anonymous Functions 18

Posted by Loren Shure,

One of the reasons I like using anonymous functions is because they allow me to express whatever function I want to use as a function of the relevant arguments in different contexts.

Contents

Example

Here's a very general way I can write the code meant to generate points on a straight line.

straightline = @(X,slope,intercept) slope*X + intercept
straightline = 
    @(X,slope,intercept)slope*X+intercept

Choose a Particular Line to Plot

First let's choose a particular straight line segment. I start by defining the slope and intercept values.

m = 2;  % slope
b = -3; % intercept

Plot the Line

Now I can evaluate my function when I create the plot.

x = 2:0.1:5;
plot(x,straightline(x,m,b))

Find Area Under the Line

Now let's find the area under a segment of this line, between two points. Since the function integral requires the integrand to be a function of one variable only, we can use the anonymous function myline, defined below, to create just such a representation.

lowerlimit = 2;
upperlimit = 5;

Create a function representing my particular line segment, by fixing those slope and intercept values, and creating a new function from the original one.

myline = @(x) straightline(x,m,b);

Use this new function, myline, as the integrand.

myarea = integral(myline, lowerlimit, upperlimit)
myarea =
    12

Find Best Fit Line

Now suppose we have data, based on this line segment, that has some noise. And we would like to estimate the slope and intercept values.

m = 2;
b = -2;
t = (2:0.2:5)';
data = straightline(t,m,b) + 0.2*randn(size(t));
plot(t,data,'m*')

Now I want slope and intercept to be my independent variables. I can use polyfit. Of course, I could use \ as well.

p = polyfit(t,data,1);

Now compare estimates for slope and intercept to original values.

comparison = [m, b; p]
comparison =
            2           -2
        2.094      -2.3638

Perhaps I instead want a function of the slope and intercept only. In that case, with data supplied, I can derive such a function from straightline. I can even get the values put into a

slopeIntercept = @(slope,intercept) straightline(data, slope, intercept);
slp = [1 4]; intcpt = [0 -5];
newline1 = @(X) straightline(X, slp(1), intcpt(1));
newline2 = @(X) straightline(X, slp(2), intcpt(2));

Anonymous Functions Allow Interface Flexibility

Using the same original function definition for straightline, I am able to mold the function for different purposes. In the first case, I turned my function of 3 variables into a function of one variable, with preset parameters. I could also use it to create a function of just slope and intercept, suitable for create line segments for different parameters at a later time.

In fact, if I was trying to use my straightline function with some other code that required lines to be defined by slope and intercept first, and then the abscissa, I can easily create a new interface for the line.

differentLine = @(slope, intercept, X) straightline(X, slope, intercept);

Have You Used Anonymous Functions to Alter the Interface?

I'd love to hear your thoughts here.


Get the MATLAB code

Published with MATLAB® 7.14

18 CommentsOldest to Newest

Anonymous functions are work very slow in MATLAB. But they are very useful to use.

I like to use just for fun, for example:

% swap
a = 10; b = 20;
swap = @(a,b)deal(b,a)
[a,b] = swap(a,b)

% Currying and closure
% unfortunately, curry(5)(6) is not supported
curry = @(x)@(y)x+y;
a = curry(5);
a(6); % 11

% Partial function application
size1 = @(x)size(x,1)
rows = size1(zeros(4,5))

:)

In general, anonymous functions – a very powerful and convenient.

Is there a way to use anonymous functions with several lines ? It seems to me that only one line anonymous functions are supported.
It would be an extremely useful feature to be able to create and use functions in a script.

Bogdan,

Multi-line anon. functions are allowed, at least in R2012a:

>> f = @(x,y)…
(x+1)*y;
>> f(1,2)
ans = 4

I sometimes use anonymous functions to temporarily override functions. For example, putting

log = @reallog; sqrt = @realsqrt;

at the top of some code might help me find where unwanted complex numbers are coming from.

To give one application of the methods Evgeny mentioned, I often use anonymous functions to hide data from optimizers

cf = @(parameters) cost_function(data, parameters);
optimal_parameters = optimizer(init_parameters, cf);

I am wary of returning anonymous functions in Matlab though. As long as an anonymous function is alive, the entire environment in which it was created isn’t freed, which can lead to unexpected and wasteful memory use: http://homepages.inf.ed.ac.uk/imurray2/compnotes/octave_matlab.html#capture

Hi Loren,

I’ve used anonymous functions for exactly the purpose you mentioned: for interface flexibility. Particularly, I’ve used it as a crude implementation of Gamma et al.’s Visitor design pattern.

Anonymous functions are a nice middle ground between a full-blown object-oriented design and a purely functional-procedural design.

Cheers,

Laurens

MATLAB also supports “anonymous functions” written in Groovy and Java: if Groovy is installed on the MATLAB javaclasspath, a Groovy closure can be assigned to a MATLAB variable and treated much as MATLAB anonymous function (but with copying of primitive data arrays on input/output so MATLAB generally still the preferred option there). Java 8 will add closures or “lambda functions” to Java.

What I’m sure Drzick and Bogdan meant is to create multi-statement anonymous functions. It’s the one thing R has I wish MATLAB had.

I’d love to be able to write something like

doubleplot = @(x,a,b) …
subplot(1,2,1),varargout{1} = plot(x,a); …
subplot(1,2,2),varargout{2} = plot(x,b);

… and then be able to call

[ha hb] = doubleplot([1 2],[1 1],[2 1]);

… and see two subplots appear in the Figure and two handles to axes objects appear in the workspace.

Carl –

I understand the desire for multi-statement anonymous functions. Right now, plot returns handles to the entities that are plotted, not to their axes.

If I understand your example, you would like that to change maybe (in addition to the multi-statements)?

–Loren

Loren, is there any possibility of changing the way that anonymous functions snapshot their environment, so that only variables that are explicitly reference in the anonymous function definition are stored in it? From my brief thinking, the only behavior change that this would introduce is if existing user code plays ‘games’ with eval() in the anonymous function to access the non-explicitly referenced variables – this would no longer work, but do you think many users do this? It’s not documented functionality…

The current behavior can be unnecessarily memory/HD intensive, and in my experience has caught many programmers off guard… This is not helped by the fact that the documentation makes it sound like they only store referenced variables: http://www.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html . Also, the wording of the following phrase could be improved, from “To supply different values for the coefficients, you must create a new function handle:” to “…you must redefine the function handle:”

Cheers

Eric-

The long-term plan is to have anonymous functions pick up only what they need from the environment. That is on the enhancement list for the language. For now, there is no way to avoid it – best to create the anonymous functions from a function if memory is an issue.

It would be helpful if you submitted the other wording and doc enhancements on mathworks.com. Thanks.

–Loren

I’ve been using Anonymous functions for over a year now, primarily as arguments for the fmincon() function [used for constrained non-linear optimization].
I’ve to admit, though, I’d never understood its full potential, and after reading thru this nice article, more doubts haunt me.

For instance, in standalone cases, I haven’t see any difference while creating or calling anonymous functions with @(x) or @(x,y) or @(x)@(y).

As regards the above article, my understanding of the following lines of code is that:

myline = @(x) straightline(x,m,b);

is equivalent to myline(x);
and that

slopeIntercept = @(slope,intercept) straightline(data, slope, intercept);

is equivalent to slopeIntercept(slope,intercept), which in turn invokes straightline(…).

newline1 = @(X) straightline(X, slp(1), intcpt(1));

translates as newline1(X), which then calls straightline().

differentLine = @(slope, intercept, X) straightline(X, slope, intercept);

is the same as calling straightline() with a different order of parameters.
Please correct me if I’m wrong.

Could you shed further light on the issue, including multi-variable anonymous functions, & if possible, illustrate with examples where necessary?

Further, in case anyone’s used fmincon(), could you please share your experience and explain further? For instance, is it possible to optimize the function with multiple variables, in which case, you might need to use multi-variable anonymous functions as arguments to the objective function & the constraint function?

Thanks,
Navin.

Navin-

I don’t understand your comment/code for the stand-alone cases you mention, especially @(x)@(y).

Your understanding of the meanings of the other calls is correct.

I am not clear what you want to see about multi-variable inputs. Can you say more?

–Loren

Thanks Lori, it will be very nice when anonymous functions only grab referenced variables.

Do you think the DISP function could be modified to show the value of the captured variables, instead of the variable names? This would help people realize that they are indeed captured/frozen instead of taking on new ‘live’ values at the time of execution…

for instance:

>> a = 3.14;
>> fn = @(x) a*x.^2

fn =

@(x) 3.14*x.^2 % instead of current @(x) a*x.^2

>>

Eric-

We intentionally do not show values in anonymous function displays. What if the variables to display had size 1000×1000; would you really want to see that? Doubtful. Technically, you can have a new function that you use to show that information, and possibly could overload display.

Please feel free to request this as an enhancement using the link to Technical Support on the right of my blog.

–Loren

Thanks Loren (sorry for the name mixup earlier, I had just been talking to someone named Lori :)

I understand your point, I suppose I just haven’t had the need to use arrays/strings/etc in an anonymous function.

What do you think about modifying DISP to display the workspace contents captured in the anonymous function, using a display format similar to WHOS? I’m thinking something like this:

>> a = 1;
>> b = rand(10);
>> c = ‘test';
>> fn = @(x) a*x.^2

fn =

@(x)a*x.^2

Captured variables:
Name Size Bytes Class Attributes

a 1×1 8 double
b 10×10 800 double
c 1×4 8 char

These postings are the author's and don't necessarily represent the opinions of MathWorks.