# Is it possible to write several statements into an anonymous function?

246 views (last 30 days)

Show older comments

Hi all,

I would like to write the following statements into a function

z=zeros(5);

z(1,1)=x(1)*cos(x(2));

z(3,4)=log(x(3));

Is is possible to write this into an anonymous function somehow?

thanks,

Patrick

##### 9 Comments

### Answers (10)

Walter Roberson
on 8 Oct 2012

Edited: Walter Roberson
on 8 Oct 2012

Also, an if/else can be coded in function form by using

FHEXEC = @(FH) FH();

FHSELECT = @(TF,CONDITION) TF(CONDITION==[true,false]);

IF = @(CONDITION,TRUEFUNC,FALSEFUNC) FHEXEC( FHSELECT([TRUEFUNC,FALSEFUNC],CONDITION) )

Then, for example,

if x>3; sin(x); else cos(x); end;

can be coded as

IF(x>3, @(sin(x)), @(cos(x)))

Jamie
on 16 Apr 2016

Anonymous functions support only expressions, so multiple-statement procedural code must be transformed into functional style. The pain points in this transformation are control statements, such as if/then, which are not available, and assignment, which is unnatural at best in functional languages. (Matlab-without-statements could be considered a functional language, albeit an awful one.)

One way to think of the procedural-to-functional transformation is to imagine each statement (potentially with side-effects) as a function applied to the environment that returns a new environment.

To take your example, I might use a structure 's' to represent a local environment, and each statement transforms the environment. Stealing from Walter's clever helper functions:

ASGN = @(A,B,S) subsasgn(A, struct('type', '()', 'subs', {B}), S);

then:

x = [ 1 2 3 ];

f1 = @(s) setfield(s, 'z', zeros(5)); % z = zeros(5);

f2 = @(s) setfield(s, 'z', ASGN(s.z, {1,1}, x(1)*cos(x(2)))); % z(1,1)=x(1)*cos(x(2));

f3 = @(s) setfield(s, 'z', ASGN(s.z, {3,4}, log(x(3)))); % z(3,4)=log(x(3));

f4 = @(s) s.z; % equivalent to "return z"

f4(f3(f2(f1(struct()))))

To invoke functions that have no output value as statements, we need a "no-op" function that passes the environment unmodified but forces evaluation of other parameters:

nop = @(s, varargin) s; % evaluates other arguments while passing environment unmodified

x = [ 1 2 3 ];

f1 = @(s) setfield(s, 'z', zeros(5)); % z = zeros(5);

f2 = @(s) setfield(s, 'z', ASGN(s.z, {1,1}, x(1)*cos(x(2)))); % z(1,1)=x(1)*cos(x(2));

f3 = @(s) setfield(s, 'z', ASGN(s.z, {3,4}, log(x(3)))); % z(3,4)=log(x(3));

f4 = @(s) nop(s, fprintf('hello world\n')); % fprintf('hello world\n');

f5 = @(s) s.z; % equivalent to "return z"

f5(f4(f3(f2(f1(struct())))))

To perform if/then, again I'll borrow Walter's idea: if we're operating on continuations we can implement a ternary operator to choose the appropriate continuation, and then evaluate it. If I have

ftrue = @(s) setfield(s, 'z', ASGN(s.z, {2,2}, 99));

ffalse = @(s) setfield(s, 'z', ASGN(s.z, {3,3}, 10));

and a simple ternary (without short-circuit)

ternary = @(c,varargin) varargin{2-logical(c)}; % returns second or third argument

then I can implement a conditional which applies one or the other continuations

ftrueorfalse = @(s) feval(ternary(s.z(1,1) < 0, ftrue, ffalse), s);

Finally to avoid assigning temporary variables just to be able to "f5(f4(f3(f2(f1(struct())))))", we can implement the equivalent of a begin/end construct that takes any number of @(s)... style functions and composes them and returns single @(s)... function. This will also be necessary for multiple statements in an if/else block. For simplicity these helper functions are not anonymous:

% given statements, generate function that applies all of them to an environment

function f = compose(varargin)

f = @(s) applyeach(s, varargin{:});

end

% given environment and statements, apply each statement to the environment in turn

function s = applyeach(s, varargin)

for i=1:length(varargin)

s = varargin{i}(s);

end

end

Finally, all together, procedural code can be more-or-less one-to-one translated into a (admittedly ugly) composition of functions, for example:

x = [ 1 2 3 ];

z = zeros(5);

z(1,1) = x(1)*cos(x(2));

z(3,4) = log(x(3));

fprintf('hello world\n');

if z(1,1) > 0

fprintf('true branch\n');

z(2,2) = 99;

else

fprintf('false branch\n')

z(3,3) = 10;

end

% return z

Translates into:

x = [ 1 2 3 ];

f = @() feval(compose(...

@(s) setfield(s, 'z', zeros(5)), ...

@(s) setfield(s, 'z', ASGN(s.z, {1,1}, x(1)*cos(x(2)))), ...

@(s) setfield(s, 'z', ASGN(s.z, {3,4}, log(x(3)))), ...

@(s) nop(s, fprintf('hello world\n')), ...

@(s) feval(ternary(s.z(1,1) > 0, ... % "if"

compose( ... % "begin block"

@(s) nop(s, fprintf('true branch\n')), ...

@(s) setfield(s, 'z', ASGN(s.z, {2,2}, 99)) ...

) ... % "end block"

, ... % "else"

compose( ... % "begin block"

@(s) nop(s, fprintf('false branch\n')), ...

@(s) setfield(s, 'z', ASGN(s.z, {3,3}, 10)) ...

) ... % "end block"

), s), ... % "end if"

@(s) s.z ... % "return z"

), struct());

Now, as for whether this is desirable? It depends. Clearly the syntax is ugly, so you wouldn't want to do this more than you had to. Speed is an open question but might not matter depending on the application.

To me it seems the snide objections to the original question are mostly ignorant of why you would want to use anonymous functions at all, much less why multi-statement anonymous is somehow never needed while single-expression anonymous is useful. Yes, much of what anonymous functions can do is also possible with inner (nested) functions, but this also argues that there is no point to anonymous functions at all, since you can always just define a one-line inner function and refer to it.

I can see at least a couple reasons for anonymous functions instead of inner functions that go beyond single statements:

- Anonymous functions bind variables from the outer scope at the time they are defined, unlike inner functions that use variables from the outer scope at the time they are used. Variables from the outer scope that are used in inner functions can be dangerous in that the scope of effect is more difficult to trace, akin to global variables. Anonymous functions do not suffer from this.
- Some algorithms are much more intuitive when written procedural style with multiple assignments.Patrick's original question is an example of this, and while equivalent behavior can be achieved with reshape, it is less clear what the output will be.

Regards,

-Jamie

##### 4 Comments

Jamie
on 2 May 2016

Hmm, it appears that set() seems to have its own rules, which are version-dependent. 2014a blows up on your feval(xyxy) but 2015b succeeds, and x = set(gcf, 'visible','on'); also succeeds in 2015b. But even in 2015b, if I define my own 'noret' function (not anonymous)

function noret(a, b) % no return value

fprintf('a, b: %d %d\n', a, b);

end

then feval of an anonymous function that calls noret still fails on too many output arguments.

The best I could do is to make my own (non-anonymous) feval that does not attempt to get an output value and just returns a dummy value so it will not barf when used in an expression.

function dummy = feval_discard(f, varargin)

feval(f, varargin{:}); % nargout will be zero

dummy = 0;

end

I'm stumped as to how to do this 'anonymously'.

Matt J
on 8 Oct 2012

No, anonymous functions have to consist of a single statement, but your commands can be expressed as a single statement this way

z=@(x) reshape( [x(1)*cos(x(2)), zeros(1,16), log(x(3)), zeros(1,7)], [5,5]);

Not sure why you wouldn't just put it in a normal function or nested function, though.

##### 6 Comments

per isakson
on 8 Oct 2012

Do you assume that "reparsing each specification and writing a separate file in each case" is a problem because of the time it takes?

"I can do it without knowing in advance how many specifications". When and how is data for the new specifications supplied?

Walter Roberson
on 8 Oct 2012

z = @(x) subsasgn(subsasgn(zeros(5), struct('type', '()', 'subs', {1,1}), x(1)*cos(x(2)))), struct('type', '()', 'subs', {3,4}), log(x(3));

(Note: bracket count might be wrong)

You might want to use an auxillary function:

ASGN = @(A,B,S) subsasgn(A, struct('type', '()', 'subs', B), S);

z = @(z) ASGN(ASGN(zeros(5), {1,1}, x(1)*cos(x(2)))), {3,4}, log(x(3)));

##### 0 Comments

Daniel Shub
on 8 Oct 2012

It is a little odd but ...

f = @(x)(reshape([x(1)*cos(x(2)), zeros(1, 16), log(x(3)), zeros(1, 7)], [5, 5]));

##### 0 Comments

Andrew Cramer
on 27 Mar 2013

Edited: Walter Roberson
on 27 Mar 2013

A little old but I have a solution that may be interesting to some.

Solution:

I wrote a function ExecMany(varargin) which executes each of the function handles supplied to it.

Why did I want to?

I wanted this functionality when making a GUI, by using anonymous functions I could hard code the guicontrol handles into the anonymous function which gets made when specifying callbacks.

- A nested function could do it but when the main function finishes the variables are no longer guaranteed to exist, what happens when a nested function is called outside its parent function?
- A function at the end of the file or in the working directory could do it but it wouldn't know what handles to use
- Global variables could fix that, but that's messy, inelegant and the user of my GUI gets to see all my variables and play with them.
- Reshape, or making an array etc doesn't work for functions like set(...) who don't return anything.
- Anonymous functions can have the handles hard coded, don't pollute the global namespace and don't make gratuitous numbers of files of 1 line functions. In addition, the definition of the function is close to the uicontrol, in some cases, it can be defined along with the uicontrol.

Muthu Annamalai
on 8 Oct 2012

Great answers everyone; the best solution for this problem might still be 'reshape' based answer by Walter, Daniel and Matt - each separately.

I would think easiest way to achieve multiple statement anonymous functions should be through evaluating them, i.e. using evalc().

Its not a great idea, but its something that works.

##### 2 Comments

Are
on 15 Oct 2015

Edited: Are
on 15 Oct 2015

This case is old, but I stumbled upon it today. The easiest way to get multiple statements into an anonymous function, is by using the eval function (or evalin). This is not fast nor space saving, but it could be useful in cases where your MATLAB program is (MATLAB compiler) compiled into an executable, and you can input anonymous functions by text.

@(x)eval('disp(1);disp(2)');

##### 2 Comments

Stephen23
on 23 Feb 2016

### See Also

### Categories

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!