224 views (last 30 days)

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?

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

Roger Stafford
on 5 Jan 2015

Try this:

f = @(x) (x.^2>=x).*x.^2+(x.^2<x).*x

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.

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
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'.

Sign in to comment.

Sign in to answer this question.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.