您可以在 Matlab 中使用匿名函数执行此操作,该函数使用 dbstack() 自省来获取自身的函数文字,然后对其进行评估。(我承认这是作弊,因为 dbstack 可能应该被认为是语言外的,但它在所有 Matlabs 中都可用。)
f = @(x) ~x || feval(str2func(getfield(dbstack, 'name')), x-1)
这是一个从 x 开始倒数然后返回 1 的匿名函数。它不是很有用,因为 Matlab 缺少 ?: 运算符并且不允许匿名函数内部的 if 块,因此很难构造基本案例/递归步骤形式。
您可以通过调用 f(-1); 来证明它是递归的;它将倒数到无穷大并最终引发最大递归错误。
>> f(-1)
??? Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N)
to change the limit. Be aware that exceeding your available stack space can
crash MATLAB and/or your computer.
您可以直接调用匿名函数,无需将其绑定到任何变量,只需将其直接传递给 feval。
>> feval(@(x) ~x || feval(str2func(getfield(dbstack, 'name')), x-1), -1)
??? Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N)
to change the limit. Be aware that exceeding your available stack space can
crash MATLAB and/or your computer.
Error in ==> create@(x)~x||feval(str2func(getfield(dbstack,'name')),x-1)
为了使它有用,您可以创建一个单独的函数来实现递归步骤逻辑,使用“if”来保护递归案例不被评估。
function out = basecase_or_feval(cond, baseval, fcn, args, accumfcn)
%BASECASE_OR_FEVAL Return base case value, or evaluate next step
if cond
out = baseval;
else
out = feval(accumfcn, feval(fcn, args{:}));
end
鉴于此,这里是阶乘。
recursive_factorial = @(x) basecase_or_feval(x < 2,...
1,...
str2func(getfield(dbstack, 'name')),...
{x-1},...
@(z)x*z);
你可以在没有绑定的情况下调用它。
>> feval( @(x) basecase_or_feval(x < 2, 1, str2func(getfield(dbstack, 'name')), {x-1}, @(z)x*z), 5)
ans =
120