Search code examples
matlabrecursioninlineanonymous-function

Recursive inline anonymous function in script


I try to write a recursive inline anonymous function in a Matlab script.

Here an MWE:

funR = @(x) [x(1) funR(x(2:end))];
funR(0:5);

But this throws the following exception:

Undefined function or variable 'funR'.

This works when it's run in a function file but not when run in a script. This is because Matlab does read those differently.

My expected result from this MWE is:

[0, 1, 2, 3, 4, 5]

How to do this right?

The goal is to have funR defined as inline function, therefore a two or more line solution is not what I want. Please ignore if this or the MWE makes any sense, that is not the point of this question.


Solution

  • You cannot do this as the the functions and variables used inside of the anonymous function must be defined at the time of creation rather than the time of execution and the anonymous function itself isn't defined until after assignment.

    The correct approach to writing a recursive anonymous function is to provide a second input to your anonymous function which is the anonymous function itself such that the anonymous function can call itself using that function handle.

    funR = @(x, funR) [x(1) funR(x(2:end), funR)];
    funR(0:5, funR)
    

    This won't work for you because you need to stop the iteration at some point. There is a great series of articles on functional programming with anonymous functions written by Loren at the Mathworks that covers this. Borrowing from that article, we can use the iif anonymous function to allow our anonymous function to properly terminate when it hits the end of the array.

    % From the article linked above
    iif = @(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
    
    % Recurse as long as there is more than one element in x 
    funR = @(x,funR)iif(numel(x) > 1,   @()[x(1), funR(x(2:end), funR)], ...
                        true,            x);
    
    funR(0:5, funR)
    

    All of this aside, from a performance perspective this is likely going to yield poor results. There is likely a vectorized way of approaching this problem that doesn't require recursive anonymous functions.