dbstack() イントロスペクションを使用してそれ自体の関数リテラルを取得し、それを評価する無名関数を使用して、Matlab でこれを行うことができます。(dbstack はおそらく言語外であると見なされるべきであるため、これは不正行為であることは認めますが、すべての Matlab で利用できます。)
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