递归匿名函数Matlab
Recursive Anonymous Function Matlab
我知道这不是创建匿名函数的目的,但就像一个谜一样,我试图通过匿名函数创建一个递归函数。递归函数的原型显然是阶乘函数。问题是在匿名函数中很难区分大小写。到目前为止我设法做的如下:
f=@(cn,n,f)eval('if n>1; f(cn*n,n-1,f);else;ans=cn;end');
f=@(n)f(1,n,f);
或者:
f=@(cn,n,f)eval('if n>1; f(cn*n,n-1,f);else;disp(cn);end');
f=@(n)f(1,n,f);
不太满意的是直接赋值还是不能使用这个函数,a=f(3)
还是报错,因为eval
没有取到值
所以我的问题是,你真的可以通过匿名函数来执行递归函数吗?以允许例如的方式计算阶乘a=f(3)
仅依赖本机 matlab 函数(或您可以在命令行中创建的函数,就像我在示例中所做的那样)?
PS:我知道这没有任何实际用途,这只是一个挑战,你可以弯曲和滥用 Matlab 的语法。
我们现在发现了两种可能性,都依赖于元胞数组的使用。请注意,这在 Octave 中可能不起作用。
关键是区分大小写的实现。我找到的第一个,可以找到 here.
该方法利用了matlabs的布尔值,true可以计算为1
,false可以计算为0
.
if_ = @( pred_, cond_ ) cond_{ 2 - pred_ }();
这里我们必须提供一个条件作为第一个参数,一个 2 元素元胞数组作为第二个参数。每个单元格元素都应该是一个函数句柄,如果条件为 true/not 真则调用该函数句柄。我们的阶乘函数如下所示:
fac = @(n,f)if_(n>1,{@()n*f(n-1,f),@()1})
factorial_=@(n)fac(n,fac);
factorial_(10)
正如@AndrasDeak 在下面评论的那样:这里的重要部分是我们有一个 函数 而不是 值 的元胞数组。这提供了短路,因为除非我们调用相应的函数 @()n*f(n-1,f)
.
,否则不会评估 n*f(n-1,f)
second method 是由@beaker 发现的并且更灵活一些:
iif = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
这利用了即使在匿名函数中也可以使用 varargin
(可变数量的参数)这一事实。当你调用这个函数时,你必须交替条件,如果条件为真,应该执行什么。这个甚至允许 switch
构造或 if ... else if ... else if ... (...) else ...
构造。调用时,它将查找第一个为真的条件 ( find([varargin{1:2:end}], 1, 'first')
) 并调用相应的函数。我们的阶乘函数示例如下所示:
fac = @(n,f)iif(n>1,@()n * f(n-1,f),true,@()1);
factorial_=@(n)fac(n,fac);
factorial_(10)
编辑:有趣的事实:我们正在用这条线做什么
factorial_=@(n)fac(n,fac);
也称为应用 Y-combinator。事实上我们可以写成
Y = @(f)@(x)f(x,f);
factorial_=Y(f);
我知道这不是创建匿名函数的目的,但就像一个谜一样,我试图通过匿名函数创建一个递归函数。递归函数的原型显然是阶乘函数。问题是在匿名函数中很难区分大小写。到目前为止我设法做的如下:
f=@(cn,n,f)eval('if n>1; f(cn*n,n-1,f);else;ans=cn;end');
f=@(n)f(1,n,f);
或者:
f=@(cn,n,f)eval('if n>1; f(cn*n,n-1,f);else;disp(cn);end');
f=@(n)f(1,n,f);
不太满意的是直接赋值还是不能使用这个函数,a=f(3)
还是报错,因为eval
没有取到值
所以我的问题是,你真的可以通过匿名函数来执行递归函数吗?以允许例如的方式计算阶乘a=f(3)
仅依赖本机 matlab 函数(或您可以在命令行中创建的函数,就像我在示例中所做的那样)?
PS:我知道这没有任何实际用途,这只是一个挑战,你可以弯曲和滥用 Matlab 的语法。
我们现在发现了两种可能性,都依赖于元胞数组的使用。请注意,这在 Octave 中可能不起作用。
关键是区分大小写的实现。我找到的第一个,可以找到 here.
该方法利用了matlabs的布尔值,true可以计算为1
,false可以计算为0
.
if_ = @( pred_, cond_ ) cond_{ 2 - pred_ }();
这里我们必须提供一个条件作为第一个参数,一个 2 元素元胞数组作为第二个参数。每个单元格元素都应该是一个函数句柄,如果条件为 true/not 真则调用该函数句柄。我们的阶乘函数如下所示:
fac = @(n,f)if_(n>1,{@()n*f(n-1,f),@()1})
factorial_=@(n)fac(n,fac);
factorial_(10)
正如@AndrasDeak 在下面评论的那样:这里的重要部分是我们有一个 函数 而不是 值 的元胞数组。这提供了短路,因为除非我们调用相应的函数 @()n*f(n-1,f)
.
n*f(n-1,f)
second method 是由@beaker 发现的并且更灵活一些:
iif = @(varargin) varargin{2*find([varargin{1:2:end}], 1, 'first')}();
这利用了即使在匿名函数中也可以使用 varargin
(可变数量的参数)这一事实。当你调用这个函数时,你必须交替条件,如果条件为真,应该执行什么。这个甚至允许 switch
构造或 if ... else if ... else if ... (...) else ...
构造。调用时,它将查找第一个为真的条件 ( find([varargin{1:2:end}], 1, 'first')
) 并调用相应的函数。我们的阶乘函数示例如下所示:
fac = @(n,f)iif(n>1,@()n * f(n-1,f),true,@()1);
factorial_=@(n)fac(n,fac);
factorial_(10)
编辑:有趣的事实:我们正在用这条线做什么
factorial_=@(n)fac(n,fac);
也称为应用 Y-combinator。事实上我们可以写成
Y = @(f)@(x)f(x,f);
factorial_=Y(f);