递归匿名函数 Matlab [英] Recursive Anonymous Function Matlab

查看:42
本文介绍了递归匿名函数 Matlab的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I know that this is not what anonymous functions are made for, but just as a puzzle I tried to make a recursive function via anonymous functions. The prototype of recursive functions obviously is the factorial function. The problem is that it is difficult to make a case distinction within the anonymous functions. What I managed to do so far is following:

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没有得到一个值.

What is not very satisfactory is that you still cannot use this function when directly assigning, a=f(3) still produces an error, since eval does not get a value.

所以我的问题是,你真的可以通过匿名函数来做一个递归函数,例如以允许例如的方式计算阶乘a=f(3) 仅依赖原生 matlab 函数(或您可以在命令行中创建的函数,就像我在示例中所做的那样)?

So my question is, can you actually do a recursive function via anonymous functions that e.g. calculates factorial in a way that allows e.g. a=f(3) with relying only on native matlab functions (or functions you can create in the command line, as I did in my example)?

PS:我知道这没有任何实际用途,这只是一个挑战,你可以在多大程度上弯曲和滥用 Matlab 的语法.

PS: I know this does not have any practical use, it is just a challenge on how much you can bend and abuse Matlab's syntax.

推荐答案

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

We found two possibilites now, both rely on the use of cell arrays. Note that this might not work in Octave.

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

The key was an implementation of a case distinction. The first one that I found, can be found here.

这个方法使用了matlabs的布尔值,true可以被评估为1,而false可以被评估为0.

This method makes use of matlabs boolean values, true can be evaluated as 1 while false can be evaluated as 0.

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

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

Here we have to provide a condition as first argument, and a 2 element cell array as second argument. Each cell element should be a function handle that is called if the condition is true/not true. Our factorial function would look like this:

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

As @AndrasDeak commented below: The important part here is that we have a cell array of functions and not of values. This provides the short circuiting, as n*f(n-1,f) is not evaluated unless we call the corresponding function @()n*f(n-1,f).

第二种方法 是@beaker 发现的,而且更加灵活:

The second method was found by @beaker and is somewhat more flexible:

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') )并调用相应的函数.我们的阶乘函数示例如下所示:

This makes use of the fact that you can use varargin (variable amount of arguments) even in anonymous functions. When you call this function you have to alternate conditions and what should be executed if the condition is true. This one even allows a switch construct, or a if ... else if ... else if ... (...) else ... construct. When called, it will look for the first condition that is true ( find([varargin{1:2:end}], 1, 'first') ) and call the corresponding function. Our example of the factorial function looks like this:

fac = @(n,f)iif(n>1,@()n * f(n-1,f),true,@()1);
factorial_=@(n)fac(n,fac);
factorial_(10)

<小时>

有趣的事实:我们用这条线做什么


Fun fact: What we are doing with the line

 factorial_=@(n)fac(n,fac);

也称为应用Y-combinator.事实上我们可以把它写成

is also known as applying the Y-combinator. In fact we can write that as

 Y = @(f)@(x)f(x,f);
 factorial_=Y(f);

这篇关于递归匿名函数 Matlab的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆