MATLAB Answers

Defining anonymous function using an "if" statement

285 views (last 30 days)
John
John on 5 Jan 2015
I'm trying to define an anonymous function using an "if" statement. Here is a minimum "not working" example (my code is more convoluted, but this illustrates the issue):
clc;
clear all;
f=@(x)x^2;
g=@(x) x;
if f(x)>=g(x)
h=@(x) f(x)
else h=@(x) g(x)
end
The point is that I don't want to create an m file and have to recompute both f and g in it (my actual problem would require recomputing many more). So the question is:
1-) Is it possible to create an anonymous function using "if" statements (fixing the code above)?
2-) Is it possible to define function h on a separate m file, without having to recompute f and g inside of it?

  0 Comments

Sign in to comment.

Accepted Answer

Matt J
Matt J on 5 Jan 2015
You can also do things like the following
f=@(x)x^2;
g=@(x) x;
h=@(x) fg_mfile(x,f,g);
function out=fg_mfile(x,f,g) %put this in mfile
fval=f(x);
gval=g(x);
if fval>=gval
out=fval;
else
out= gval;
end
end

  2 Comments

yang
yang on 24 Aug 2018
you can do like this h=@(x)max(f(x),g(x))
Matt J
Matt J on 24 Aug 2018
In this particular example, that is true. More complicated h() might require an mfile to express, however.

Sign in to comment.

More Answers (2)

Roger Stafford
Roger Stafford on 5 Jan 2015
Try this:
f = @(x) (x.^2>=x).*x.^2+(x.^2<x).*x

  5 Comments

Show 2 older comments
Matt J
Matt J on 6 Jan 2015
This is a classic technique and Star Strider is right. More generally, you would do
h = @(x) L(x).*f(x) + (~L(x)).*g(x)
where L(x) is a possibly multivariate indicator function of x (i.e. =1 when f is active and =0 if g is active).
The only thing I'd point out is that it requires L(x) to be computed twice. It also requires that both f and g be computed even though you really only want to compute the one that is active. With a dedicated mfile you can often avoid that.
So, for large calculations, it has its drawbacks in CPU efficiency, but advantages in syntax efficiency.
John
John on 6 Jan 2015
I see. I checked the references you provided and now I understand.
Alec Jacobson
Alec Jacobson on 16 Dec 2016
This style/hack has two (more) "gotchas".
1) Suppose L(x) is true, but g(x) produces nan/inf. Then h(x) = nan rather than f(x).
2) Suppose L(x) is true and g(x) is very expressive to compute or has side-effects (admittedly rare for matlab code), g(x) will still be called. This is very different behavior from:
if L(x)
return f(x)
else
return g(x)
I really wish matlab had full-citizen anonymous functions...

Sign in to comment.


Cristobal Montecino
Cristobal Montecino on 26 Jun 2019
Edited: Cristobal Montecino on 26 Jun 2019
I use:
call = @(fun) fun();
cellget = @(cell, index) cell{index};
iff = @(test, truefn, falsefn) call(cellget({falsefn, truefn}, test + 1));
And:
arrayget = @(arr, index) arr(index);
ifv = @(test, trueval, falseval) arrayget([falseval, trueval], test + 1);
%or
cellget = @(cell, index) cell{index};
ifv = @(test, trueval, falseval) cellget({falseval, trueval}, test + 1);
Examples:
iff(true, @() 2, @() this_throw_an_error)
% out: 2
iff(false, @() 2, @() this_throw_an_error)
% out: Undefined function or variable 'this_throw_an_error'.
ifv(true, 2, 3)
% out: 2
ifv(true, 2, this_throw_an_error)
% out: Undefined function or variable 'this_throw_an_error'.

  1 Comment

Oscar Raya i Casanova
Oscar Raya i Casanova on 29 Jan 2020
Nice tip. As improvement for the first option:
call = @(fun,par) fun(par{:});
cellget = @(cell, index) cell{index};
iff = @(test, truefn, falsefn, truePar, falsePar) call( ...
cellget({falsefn, truefn}, test + 1), ... % functions
cellget({falsePar, truePar}, test + 1) ... % params
);
Examples:
f1 = @(a,b) a + b;
f2 = @(a,b,c) a*b + c;
f3 = @() 7;
iff(true,f1,f2,{1,2},{1,2,3});
% out: 3
iff(false,f1,f2,{1,2},{1,2,3});
% out: 5
iff(false,f1,f3,{1,2},{});
% out: 7
This way you can use functions with different number of parameters.

Sign in to comment.

Tags


Translated by