anonymous function for if-else statements

Hi, Is it possible to write an anonymous function or a function handle that replicates the behavior of if-else statements?
Consider the simple problem
if condition
a=b(x);
else
a=c(x);
end
it is possible to write the following function that will replicate that behavior
function out=ifelse(condition,answer1,answer2)
if condition
out=answer1;
else
out=answer2;
end
A critical difference between the first and the second pieces of code is the fact that in the second one, both answer1 and answer 2 need to be computed/evaluated before passing them to the ifelse function. For small problems this is not really a problem. However, in a situation where b(x) or c(x) are expensive to compute, it is best to avoid un-necessary operations.
One workaround would be
function out=ifelse2(condition,input1,input2)
if condition
out=eval(input1);
else
out=eval(input2);
end
In this case though we have to use "eval".
Is there any other way to deal with this, possibly using some kind of anonymous function or a function handle?
Thanks

1 Comment

Don't use eval. If you talk about expensive functions, the performance degradation by eval must be important.

Sign in to comment.

Answers (4)

SelectCell = @(C, idx) C{idx}
condfunc = @(x, scalarcondition, varargin) feval(SelectCell(varargin, scalarcondition+1),x)
Example:
condfunc(x, condition, @b, @c)

5 Comments

Hi Walter,
There is a mistake in your second line (+1 does not belong in there, I think). But this is along the lines of what I am thinking and close to something I have done.
The drawback, perhaps, is the systematic use of feval. The strategy I have used is to create an intermediate function handle (written to disk) that memoizes C. Then the function handle can be called using as inputs your scalarcondition and varargin. In that case then the functions are evaluated as C{idx}(varargin{:}).
Jan
Jan on 20 Jul 2017
Edited: Jan on 20 Jul 2017
Why is the use uf feval a drawback? It is fast and secure.
"Written do disk" sounds like a bottleneck. Avoid passing data through disk access, if run time matters.
Hi Jan,
Thanks for your input. In a particular problem, I may have literally thousands of places where I need this type of constructs and they are problem-specific. Sometimes I need to go in and look at a specific element for debugging purposes.
Ideally the things that I want to write to disk are the things that are not problem-specific.
At the heart of my inquiry is the question of how to turn a function that would otherwise be written to disk into an anonymous function. Maybe I should pose this question in a new thread?
When the scalarcondition is logical, then false corresponds to 0 and true corresponds to 1, and adding one to that takes it into the range 1 or 2, which is suitable for indexing a two element array. However, you might want to use 2-scalarcondition instead, to reverse the order of the tests (the first one corresponds to false in the way I wrote the code.)
My bad, I missed that possibility. I thought scalarcondition was 1 or 2. Thanks Walter.

Sign in to comment.

In R2016b and newer you can have subfunctions in scripts as well as functions. I would recommend using them instead.

4 Comments

Hi Sean,
Do you have an example of this please? I tried the following and it didn't work
test=mysubfunction(3)
function a=mysubfunction(x)
a=x+1;
end
This requires R2016b or later. It also requires that the script file be named something different than the name of any of the functions defined in the script.
So, the script has to be saved?
@Patrick Mboma: yes.

Sign in to comment.

Adam
Adam on 20 Jul 2017

1 Comment

Hi Adam,
Thanks for your input. Functional programming, although I am not expert in it, in large part inspires some of the things I do here. For instance the iff construct that is discussed in part-1 is similar to my ifelse function above and shares the same drawback that all alternatives have to be evaluated before the choice is made, which can be very costly.

Sign in to comment.

@(x) condition * b(x) + (~condition) * c(x)
But you see, that b(x) and c(x) are evaluated also. The best strategy is not to use anonymous functions, but normal functions. Then you have the full power and the best speed.

9 Comments

Hi Jan,
The normal functions you are talking about have the drawback that you have to write them to m-files. I am looking for a way to avoid writing (additional) m-files.
Maybe a bit of context might help understand why I am doing this. I have an application that solves generic problems and my ideal is that additional files not be written for every specific problem to solve.
If I were using normal functions there would not be a problem.
Are the "generic problems" being dynamically generated?
Can these functions output +/- inf, or nan ?
Hi Walter,
The application takes as input a specific problem and then puts it in a generic form. It is OK that the functions return infinities or nan from time to time. This would mean that some parameter values need to be changed.
Writing M-files is fine and in your case it might be more efficient than creating anonymous functions dynamically. Better write a "generic function", which describes the "generic problem" and control the details by input arguments. The simpler, the better.
There are functions that I would definitely write as m-files. Those functions that are used for handling generic problems.
There are other functions that are problem specific and those I would like to write them as anonymous functions. But they can be very complicated and include intermediary terms as well as if-else statements.
The anonymous functions are used as inputs to the functions written as m-files.
I am not sure what "generic form" means in this case...
The reason I ask about nan and inf is that some of the useful methods for conditional computation fail if nan or inf is involved, as they rely upon multiplication by 0 to ignore the computed value that is not wanted; that fails if the value to be ignored is nan or inf because 0*nan and 0*inf are both nan instead of 0.
Walter,
As long as only one option is evaluated at a time, nans and infs are not a problem.
Let me try to use an analogy to explain in simple terms what I am trying to do. Suppose you have a root-finding problem and you are using fsolve. You can provide fsolve with an auxiliary function computing jacobian of the problem at a given point. Assume then, for the sake of argument, that fsolve was able to generate such a jacobian function just from the knowledge of the objective function.
In the example above, I call fsolve the generic function, which is written to an m-file. But on the other hand, the jacobian function of the problem so solve depends on the problem itself. This is the function that I would like to avoid writing to an m-file, since it is generated (hypothetically) by fsolve.
I would use the Symbolic Toolbox for the kind of situation you describe.
Hi Walter,
The point is not what tools you use, but rather how you handle the output. The analogy I made above was just to make a point. Essentially, some people use my codes to solve a problem I don't know anything about. But for my codes to solve the problem, my procedures will first generate some functions that are specific to the problem at hand. Those functions are the ones I want to avoid writing to an m-file.

Sign in to comment.

Asked:

on 19 Jul 2017

Commented:

on 21 Jul 2017

Community Treasure Hunt

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

Start Hunting!