Ответ 1
Теперь мы обнаружили две возможности: оба полагаются на использование массивов ячеек. Обратите внимание, что это может не работать в Octave.
Ключ был осуществлением разграничения случая. Первый, который я нашел, можно найти здесь.
Этот метод использует логические значения matlabs, значение true может быть оценено как 1
, а false может быть оценено как 0
.
if_ = @( pred_, cond_ ) cond_{ 2 - pred_ }();
Здесь мы должны предоставить условие в качестве первого аргумента и 2-элементный массив ячеек в качестве второго аргумента. Каждый элемент ячейки должен быть дескриптором функции, который вызывается, если условие истинно/не истинно. Наша факториальная функция будет выглядеть так:
fac = @(n,f)if_(n>1,{@()n*f(n-1,f),@()1})
[email protected](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);
[email protected](n)fac(n,fac);
factorial_(10)
EDIT: Интересный факт: что мы делаем с линией
[email protected](n)fac(n,fac);
также известен как применение Y-combinator. На самом деле мы можем записать, что как
Y = @(f)@(x)f(x,f);
factorial_=Y(f);