Search code examples
matlabruntimefunction-handle

Matlab parsing at run-time of function handles


My Question: Given a function handle, does matlab parse the string each time it needs to evaluate it, or just once and then it caches it?

Example

Consider the ingenious function

function [] = foo(func)
for j=1:1e4
    func(j);
end

and the script

func1 = @(x) 5*abs(x)^2
function foo(func1);

At run-time, Matlab needs to interpret @(x) 5*abs(x)^2 as a function. In this example, does it do it once, or a thousand times?


Solution

  • First of all @(x)cos(x) is not a string, it is an anonymous function declaration. When you create an anonymous function, MATLAB essentially creates a function object which contains all of the information it needs to run. This anonymous function can then be passed around to various functions or even saved to a file. As such, it is only constructed once and evaluated many times.

    When evaluated, MATLAB does not do any caching, so calling the same anonymous function with the same inputs many times causes the contents of the anonymous function to be evaluated each time.

    If you want to get more information about your anonymous function, including the local workspace of the function, you can use the functions function

    f = @(x)cos(x);
    
    functions(f)
    
    %            function: '@(x)cos(x)'
    %                type: 'anonymous'
    %                file: ''
    %           workspace: {[1x1 struct]}
    %    within_file_path: '__base_function'
    

    That being said, in your example, it could really be reduced to a function handle rather than an anonymous function since you pass all input arguments directly to cos without modifying them. As you can see, this has a different internal representation and from some preliminary benchmarks, it seems to be marginally faster.

    f = @cos
    
    functions(f)
    
    %    function: 'cos'
    %        type: 'simple'
    %        file: ''
    

    And a quick benchmark

    function benchit
        fprintf('Anonymous function: %0.4f\n', timeit(@option1));
        fprintf('Function handle:    %0.4f\n', timeit(@option2));
    end
    
    function option2()
        f = @(x)cos(x);
        for k = 1:10000
            f(k);
        end
    end
    
    function option1()
        f = @cos;
        for k = 1:10000
            f(k);
        end
    end
    

    And the results (not really a huge difference)

    Anonymous function: 0.0056
    Function handle:    0.0049
    

    A few more things

    • When creating the anonymous function, the anonymous function declaration must still adhere to all of MATLAB's standard syntax rules otherwise it won't be created. For example, the following would throw an error during anonymous function creation since it is invalid syntax

      func = @(x)thing]
      

      Error: Unbalanced or unexpected parenthesis or bracket.

    • When you evaluate an anonymous function (after it's successful creation), it's just like evaluating any other function in that the anonymous function can throw an error and the error depends upon the input.

      func = @(x) x + [1 2];
      
      func([3 4])
      %   4   6
      
      % Now we're going to pass an array that isn't 1 x 2
      func([5 6 7])
      

      Matrix dimensions must agree.
      Error in @(x)x+[1,2]