我们现在找到了两个可能性,都依赖于使用单元数组。请注意,这在Octave中可能无法正常工作。
关键是实现一个情况区分的方法。我发现的第一个方法可以在这里找到。
此方法利用了Matlab的布尔值,其中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)
。
第二种方法由@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 = @(f)@(x)f(x,f);
factorial_=Y(f);
f(3)
,它会执行if...
,一切都好。但是如果你想要赋值a=f(3)
,它会想要做类似a= if...
的操作。我们在Matlab中非常需要一个条件三元运算符;) - Andras Deak -- Слава Україні