将函数句柄传递给 Matlab 中的其他函数时,如何保留函数句柄的参数数量?

How do I retain the number of arguments of a function handle when passing it to some other function in Matlab?

我正在尝试编写一个函数,它将函数元胞数组作为输入并输出相同的函数,但格式有所不同。

具体来说,我想要一个长度为 N 的行向量,函数 fVec = [f1(x, y, z), f2(x,y,z), ..., fn(x, y, z)] 所有这些函数总是输出相同长度的列向量,例如 M。现在我想要 fVec(x, y, z) 的评估输出一个 MXN 矩阵,其中每一列代表其对应向量的输出。

但是,由于 Matlab 不接受常规函数句柄数组,因此必须使用元胞数组来完成。 (,对吗?)

此外,我想要一个适用于多组函数的通用函数,这些函数不一定具有三个输入。也就是说,我想要函数 fVec(1, ..., x) = [f1(1, ..., x), f2(1, ..., x), fn(1, ..., x)],这意味着每个函数 f1, f2, fn 始终具有相同数量的输入。

因此,我需要一些函数将函数句柄 {f1(1, ..., x), f2(1, ..., x), fn(1, ..., x)} 的元胞数组作为输入并输出一些总体函数 fVec(1, ..., x).

我已经尝试编写一个我认为应该这样做的函数:

function overArchingFunction = transformFunctionArray(functionArray)
    if length(functionArray) == 1
        if isa(functionArray, 'cell')
            overArchingFunction = functionArray{:};
        else
            overArchingFunction = functionArray;
        end
    else
        disp(cellfun(@(fun) fun(x), functionArray, ...
                'UniformOutput', false))
        overArchingFunction = @(vars) cell2mat(cellfun(@(fun) fun(vars), functionArray, ...
                'UniformOutput', false));
    end
end

这显然适用于 "arrays of length 1"。但是,此代码存在问题。让我们创建一个测试函数,比如 testfun = @(a, b, c, d, e) a(:,3) - a(:,2)(其中 testfun 是 b, c, d, e 的函数,用于复制最一般的场景),并创建该函数的数组 functionArray = {testfun, testfun}

现在我们调用函数 overArchingFunction = transformFunctionArray(functionArray)。但是,当调用 solution = transfun([[10 1 2]; [3 4 5]], 0, 0, 0, 0) 时,我希望输出为:

solution =

     1     1
     1     1

事实并非如此,因为使用 @(vars)fun(vars) 语句,我将此函数的输入变量的数量限制为只有一个变量,而我试图通过五个参数(即 [[10 1 2]; [3 4 5]], 0, 0, 0, 0)。我虽然我会通过替换 vars 来解决这个问题 varargin,但这给了我错误:

Attempt to execute SCRIPT varargin as a function:
/MATLAB/toolbox/matlab/lang/varargin.m

总结一下,如何在overArchingFunction中保留f1, f2, ..., fn的原始输入参数数量?

我找到了。答案确实在于使用 varargin。但是,因为 varargin 传递单元格结构输入,您需要使用 varargin{:} 访问这些单元格的内容。因此函数应该是:

function overArchingFunction = transformFunctionArray(functionArray)
    if length(functionArray) == 1
        if isa(functionArray, 'cell')
            overArchingFunction = functionArray{:};
        else
            overArchingFunction = functionArray;
        end
    else
        overArchingFunction = @(varargin) cell2mat(cellfun(@(fun) fun(varargin{:}), 
            functionArray, ...
                'UniformOutput', false));
    end
end

使得以下命令给出所需的答案。

>> testfun = @(a, b, c, d, e) a(:,3) - a(:,2)

testfun =

  function_handle with value:

    @(a,b,c,d,e)a(:,3)-a(:,2)

>> transfun = transformFunctionArray({mytestfun, mytestfun})

transfun =

  function_handle with value:

    @(varargin)cell2mat(cellfun(@(fun)fun(varargin{:}),functionArray,'UniformOutput',false))

>> myans = transfun([[10 1 2]; [3 4 5]], 0, 0, 0, 0)

myans =

     1     1
     1     1