Возможно ли иметь функцию PHP, которая является как рекурсивной, так и анонимной? Это моя попытка заставить его работать, но имя функции не передается.
$factorial = function( $n ) use ( $factorial ) {
if( $n <= 1 ) return 1;
return $factorial( $n - 1 ) * $n;
};
print $factorial( 5 );
Я также знаю, что это плохой способ реализовать факториал, это всего лишь пример.
global $factorial
?print $factorial( 0);
Ответы:
Для того, чтобы он работал, вам нужно передать $ factorial в качестве ссылки
источник
&
по стоимости. Все с&
помощью ссылки. «Объекты» не являются значениями в PHP5 и не могут быть назначены или переданы. Вы имеете дело с переменной, значение которой является ссылкой на объект. Как и все переменные, он может быть захвачен по значению или по ссылке, в зависимости от того, есть ли&
.$factorial
будет изменено до вызова функции, и это может привести к странному поведению.Я знаю, что это может быть не простой подход, но я узнал о методике под названием «исправить» из функциональных языков.
fix
Функция из Haskell известна в более общем случае в качестве Y комбинатора , который является одним из самых известных точечных комбинаторов фиксированных .Фиксированная точка - это значение, которое не изменяется функцией: фиксированная точка функции f - это любой x такой, что x = f (x). Комбинатор с фиксированной точкой y - это функция, которая возвращает фиксированную точку для любой функции f. Поскольку y (f) является неподвижной точкой f, имеем y (f) = f (y (f)).
По сути, комбинатор Y создает новую функцию, которая принимает все аргументы оригинала, плюс дополнительный аргумент, который является рекурсивной функцией. Как это работает, более очевидно, используя каррированную нотацию. Вместо того , чтобы писать аргументы в скобках (
f(x,y,...)
), записать их после функции:f x y ...
. Y комбинатор определяется какY f = f (Y f)
; или с одним аргументом для рекурсивной функции,Y f x = f (Y f) x
.Так как PHP автоматически не выполняет функции карри , это немного хакерство
fix
, но я думаю, что это интересно.Обратите внимание, что это почти то же самое, что и простые решения по закрытию, опубликованные другими, но функция
fix
создает закрытие для вас. Комбинаторы с фиксированной запятой немного сложнее, чем использование замыкания, но они более общие и имеют другие применения. Хотя метод замыкания больше подходит для PHP (который не очень функциональный язык), исходная проблема - скорее упражнение, чем для производства, поэтому комбинатор Y - жизнеспособный подход.источник
call_user_func_array()
это медленно, как Рождество.call_user_func_array
.array_unshift( $args, fix($func) );
? Аргументы уже загружены параметрами, а рекурсия выполняется call_user_func_array (), так что же делает эта строка?Хотя это не для практического использования, расширение C-уровня mpyw-junks / phpext-callee обеспечивает анонимную рекурсию без назначения переменных .
источник
В новых версиях PHP вы можете сделать это:
Это может привести к странному поведению.
источник
Вы можете использовать Y Combinator в PHP 7.1+, как показано ниже:
Поиграйте с ним: https://3v4l.org/7AUn2
Исходные коды от: https://github.com/whitephp/the-little-phper/blob/master/src/chapter_9.php
источник
С анонимным классом (PHP 7+), без определения переменной:
источник