MATLAB中的逐次函数应用
Successive function application in MATLAB
如何在 MATLAB 中使用匿名函数进行连续函数应用?类似于以下内容:
g = @(x) @(y) x+y;
g(1)(2)
但是 MATLAB 在第 2 行给出错误:()-indexing must appear last in an index expression.
但以下有效:
g = @(x) @(y) x+y;
f = g(1);
f(2)
上面的脚本输出ans=3。
我对 MATLAB 不是很熟悉,但我认为在函数级别进行操作的能力使编程变得容易得多。例如,当我需要计算函数在 L^2 的某个子空间上的投影时,投影运算符和归一化等。所有输出函数都需要额外的参数来评估数值答案。
MATLAB 不支持对函数返回的函数句柄的单个表达式调用,例如 y = g(1)(2)
。但是,您可以通过使用临时变量来解决此限制:
g1 = g(1);
y = g1(2);
作为替代方案,您可以构建自己的函数来环绕此功能。
递归方法可以是:
function f = fevalIterated(f, varargin)
if ~isempty(varargin)
f = fevalIterated(f(varargin{1}), varargin{2:end});
end
而不是 y = g(1)(2)
你会调用 y = fevalIterated(g, 1, 2)
.
执行此操作的迭代方法可能更快:
function f = fevalIterated(f, varargin)
for i = 1:numel(varargin)
f = f(varargin{i});
end
正如您在 MATLAB 中询问柯里化的概念,这与此非常相似:
取消柯里化
非柯里化意味着将函数 @(x) @(y) @(z) x+y+z
转换为函数 @(x,y,z) x+y+z
。这是一个非常相似的概念,因此您可以重用 fevalIterated
的功能来构建可以像这样使用的函数 uncurry
:
g = uncurry(@(x) @(y) @(z) x+y+z);
y = g(1,2,3)
函数 uncurry
将定义为:
function uncurried = uncurry(f)
uncurried = @(varargin) fevalIterated(f, varargin{:});
柯里化
柯里化函数 @(x,y,z) x+y+z
意味着将其转换为 @(x) @(y) @(z) x+y+z
。
这里是curry
的递归实现:
function f = curry(f,N)
if N>1
f = @(first) curry(@(varargin)f(first,varargin{:}), N-1);
end
(更快的)迭代实现如下所示:
function f = curry(f,N)
for i = 1:N-1
f = @(varargin) @(last) f(varargin{:}, last);
end
您可以通过 f = curry(@(x,y,z) x+y+z, 3)
调用两者。
警告
尽管您可以在 MATLAB 中完成所有这些操作,但如果过度调用整个函数句柄,您可能会遭受明显的性能下降。
f = @(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15) ...
(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10+x11+x12+x13+x14+x15);
%%// Currying vs Comma separated list expansion
%// Comma separated list expansion
tic;
[C{1:15}] = deal(12345);
f(C{:});
toc;
%// Elapsed time is 0.000146 seconds.
%// Currying
g = curry(f,15);
tic;
for i = 1:15
g = g(12345);
end
toc;
%// Elapsed time is 0.015679 seconds.
如何在 MATLAB 中使用匿名函数进行连续函数应用?类似于以下内容:
g = @(x) @(y) x+y;
g(1)(2)
但是 MATLAB 在第 2 行给出错误:()-indexing must appear last in an index expression.
但以下有效:
g = @(x) @(y) x+y;
f = g(1);
f(2)
上面的脚本输出ans=3。
我对 MATLAB 不是很熟悉,但我认为在函数级别进行操作的能力使编程变得容易得多。例如,当我需要计算函数在 L^2 的某个子空间上的投影时,投影运算符和归一化等。所有输出函数都需要额外的参数来评估数值答案。
MATLAB 不支持对函数返回的函数句柄的单个表达式调用,例如 y = g(1)(2)
。但是,您可以通过使用临时变量来解决此限制:
g1 = g(1);
y = g1(2);
作为替代方案,您可以构建自己的函数来环绕此功能。
递归方法可以是:
function f = fevalIterated(f, varargin)
if ~isempty(varargin)
f = fevalIterated(f(varargin{1}), varargin{2:end});
end
而不是 y = g(1)(2)
你会调用 y = fevalIterated(g, 1, 2)
.
执行此操作的迭代方法可能更快:
function f = fevalIterated(f, varargin)
for i = 1:numel(varargin)
f = f(varargin{i});
end
正如您在 MATLAB 中询问柯里化的概念,这与此非常相似:
取消柯里化
非柯里化意味着将函数 @(x) @(y) @(z) x+y+z
转换为函数 @(x,y,z) x+y+z
。这是一个非常相似的概念,因此您可以重用 fevalIterated
的功能来构建可以像这样使用的函数 uncurry
:
g = uncurry(@(x) @(y) @(z) x+y+z);
y = g(1,2,3)
函数 uncurry
将定义为:
function uncurried = uncurry(f)
uncurried = @(varargin) fevalIterated(f, varargin{:});
柯里化
柯里化函数 @(x,y,z) x+y+z
意味着将其转换为 @(x) @(y) @(z) x+y+z
。
这里是curry
的递归实现:
function f = curry(f,N)
if N>1
f = @(first) curry(@(varargin)f(first,varargin{:}), N-1);
end
(更快的)迭代实现如下所示:
function f = curry(f,N)
for i = 1:N-1
f = @(varargin) @(last) f(varargin{:}, last);
end
您可以通过 f = curry(@(x,y,z) x+y+z, 3)
调用两者。
警告
尽管您可以在 MATLAB 中完成所有这些操作,但如果过度调用整个函数句柄,您可能会遭受明显的性能下降。
f = @(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15) ...
(x1+x2+x3+x4+x5+x6+x7+x8+x9+x10+x11+x12+x13+x14+x15);
%%// Currying vs Comma separated list expansion
%// Comma separated list expansion
tic;
[C{1:15}] = deal(12345);
f(C{:});
toc;
%// Elapsed time is 0.000146 seconds.
%// Currying
g = curry(f,15);
tic;
for i = 1:15
g = g(12345);
end
toc;
%// Elapsed time is 0.015679 seconds.