【问题标题】:How do I retain the number of arguments of a function handle when passing it to some other function in Matlab?将函数句柄传递给 Matlab 中的其他函数时,如何保留函数句柄的参数数量?
【发布时间】:2020-02-23 17:02:05
【问题描述】:

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

具体来说,我想要一个长度为 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

显然,这适用于“长度为 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) 语句,我将这个函数的输入变量的数量限制为只有一个变量,而我试图传递五个参数(即@987654340 @)。我虽然我会通过替换 vars 来解决这个问题 varargin,但这给了我错误:

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

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

【问题讨论】:

  • 在函数之间传递一个struct 怎么样,你的所有参数都是字段?
  • 不幸的是,我在(不可访问且因此不可变的)现有代码之上构建,其中参数被严格作为“松散”参数传递。因此,我希望尽可能接近现有代码,并尝试以我上面描述的方式接受参数。
  • 不是完全重复,但肯定是相关的:stackoverflow.com/questions/58143196/…
  • 我在这里的评论是一样的:不是所有的东西都需要是一个匿名函数。使用varargin 的常规函数​​很容易解决此问题。
  • 顺便问一下:你运行代码了吗? overArchingFunction = functionArray{:}; 应该会给你一个错误信息。

标签: matlab arguments function-handle


【解决方案1】:

我找到了。答案确实在于使用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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多