Matlab在函数句柄的运行时解析

Ami*_*giv 2 matlab runtime function-handle

我的问题:给定一个函数句柄,matlab是否每次需要对其进行求值时解析字符串,或者只调用一次然后缓存它?

考虑一下巧妙的功能

function [] = foo(func)
for j=1:1e4
    func(j);
end
Run Code Online (Sandbox Code Playgroud)

和脚本

func1 = @(x) 5*abs(x)^2
function foo(func1);
Run Code Online (Sandbox Code Playgroud)

在运行时,Matlab需要将其解释@(x) 5*abs(x)^2为函数.在这个例子中,它是一次还是一千次?

Sue*_*ver 6

首先@(x)cos(x)不是字符串,它是一个匿名函数声明.创建匿名函数时,MATLAB实际上创建了一个函数对象,其中包含运行所需的所有信息.然后可以将此匿名函数传递给各种函数,甚至可以保存到文件中.因此,它只构造一次并进行多次评估.

在评估时,MATLAB不进行任何缓存,因此多次使用相同的输入调用相同的匿名函数会导致每次都评估匿名函数的内容.

如果要获取有关匿名函数的更多信息(包括函数的本地工作空间),可以使用该functions函数

f = @(x)cos(x);

functions(f)

%            function: '@(x)cos(x)'
%                type: 'anonymous'
%                file: ''
%           workspace: {[1x1 struct]}
%    within_file_path: '__base_function'
Run Code Online (Sandbox Code Playgroud)

话虽这么说,在你的例子中,它实际上可以简化为函数句柄而不是匿名函数,因为你直接传递所有输入参数cos而不修改它们.正如您所看到的,这有一个不同的内部表示,从一些初步基准,它似乎稍微快一些.

f = @cos

functions(f)

%    function: 'cos'
%        type: 'simple'
%        file: ''
Run Code Online (Sandbox Code Playgroud)

并快速基准

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
Run Code Online (Sandbox Code Playgroud)

结果(并没有真正的巨大差异)

Anonymous function: 0.0056
Function handle:    0.0049
Run Code Online (Sandbox Code Playgroud)

还有一些事情

  • 在创建匿名函数时,匿名函数声明必须仍然遵循MATLAB的所有标准语法规则,否则将无法创建.例如,以下内容将在匿名函数创建期间抛出错误,因为它是无效语法

    func = @(x)thing]
    
    Run Code Online (Sandbox Code Playgroud)

    错误:不平衡或意外的括号或括号.

  • 当您评估匿名函数(在成功创建之后)时,它就像评估任何其他函数一样,匿名函数可以抛出错误,错误取决于输入.

    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])
    
    Run Code Online (Sandbox Code Playgroud)

    矩阵尺寸必须一致.
    @(x)x + [1,2]中的错误

  • 记录`functions`:[https://www.mathworks.com/help/matlab/ref/functions.html](https://www.mathworks.com/help/matlab/ref/functions.html) - 它但是,建议仅用于调试. (2认同)