Вы можете сделать это в 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