Рекурсивная Анонимная Функция Matlab

Я знаю, что это не то, что анонимные функции, но просто как паззл я пытался сделать рекурсивную функцию с помощью анонимных функций. Прототипом рекурсивных функций, очевидно, является факториальная функция. Проблема в том, что трудно провести различие между случаями внутри анонимные функции. Что мне удалось сделать до сих пор является следующее:

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 не получает значения.

Итак, мой вопрос в том, Можете ли вы на самом деле сделать рекурсивную функцию через анонимные функции, которые, например, вычисляют факториал таким образом, что позволяет, например,a=f(3) С опорой только на собственные функции matlab (или функции, которые вы можете создать в командной строке, как я сделал в моем примере)?

PS: Я знаю, что это не имеет практического использования, это просто вызов о том, насколько вы можете согнуть и злоупотреблять синтаксисом Matlab.

1 ответов


мы нашли две возможности сейчас, оба полагаются на использование массивов ячеек. Обратите внимание, что это может не работать в октаву.

ключом была реализация различия в случае. Первый, который я нашел, можно найти здесь.

этот метод использует логические значения matlabs, true можно оценить как 1 в то время как false можно оценить как 0.

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

здесь мы должны обеспечить условия в качестве первого аргумента и 2 массив ячеек элементов в качестве второго аргумента. Каждый элемент ячейки должен быть дескриптором функции, который вызывается, если условие true / not true. Наша факториальная функция будет выглядеть так:

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)

EDIT: забавный факт: что мы делаем с линией

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

также известен как применение Y-комбинатор. На самом деле мы можем написать это как

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