将函数句柄传递给 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
我正在尝试编写一个函数,它将函数元胞数组作为输入并输出相同的函数,但格式有所不同。
具体来说,我想要一个长度为 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