【问题标题】:Recursive Anonymous Function Matlab递归匿名函数 Matlab
【发布时间】:2015-11-21 02:48:38
【问题描述】:

我知道这不是匿名函数的用途,但作为一个谜题,我试图通过匿名函数创建一个递归函数。递归函数的原型显然是阶乘函数。问题是在匿名函数很难区分大小写。到目前为止,我设法做的事情如下:

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 的语法。

【问题讨论】:

  • 你的意思是匿名函数吗?对我来说,函数句柄似乎是一类更广泛的对象。但我不是专家,所以我真的在问。
  • @AndrasDeak 我当然知道,谢谢你指出这一点!
  • 目前没有 Matlab 访问权限,但您是否尝试过像 'if n>1; f(cn*n,n-1,f); else; cn; end 这样的事情?
  • @patrik 做了,但没有帮助:) 问题是,如果你只是调用f(3),它将执行if...,一切都很好。但是如果你想分配a=f(3),它想做类似a= if...的事情。我们非常需要 matlab 中的条件三元运算符;)
  • This 可能会有所帮助。

标签: matlab recursion anonymous-function


【解决方案1】:

我们现在发现了两种可能性,都依赖于使用元胞数组。请注意,这可能不适用于 Octave。

关键是区分大小写的实现。我找到的第一个,可以找到here.

该方法使用matlabs的布尔值,true可以计算为1,false可以计算为0

if_ = @( pred_, cond_ ) cond_{ 2 - pred_ }();

这里我们必须提供一个条件作为第一个参数,并提供一个 2 元素元胞数组作为第二个参数。每个单元格元素都应该是一个函数句柄,如果条件为真/不为真,则调用该句柄。我们的阶乘函数如下所示:

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);

【讨论】:

  • 我建议在这两种情况下都强调需要@() 来保护论点不被评估。例如,当您调用mean(rand(3)) 时,matlab 首先计算rand(3),然后将该矩阵传递给mean 函数。如果您省略 @() 部分,iif 将尝试评估当时无意义的功能。要点:iif 函数似乎在第一个 true 参数处短路,但事实并非如此。
猜你喜欢
  • 2022-06-20
  • 2011-01-29
  • 2011-04-22
  • 2020-09-24
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2011-10-24
  • 2013-07-11
相关资源
最近更新 更多