Я хочу понять, почему эта функция ничего не возвращает.
function fact($n, $p = 1) {
if ($n > 1) {
$p *= $n--;
fact($n, $p);
} else {
return $p;
}
}
var_dump(fact(5)); // NULL
Рекурсия — это циклическая конструкция, которая происходит из функциональных языков. Так что да, как уже отмечали другие, ваша функция не работает правильно, потому что правда филиал вашего if
заявление ничего не возвращает. Тем не менее, у меня есть дополнительные замечания о вашем коде
function fact($n, $p = 1) {
if ($n > 1) {
// this makes it hard to reason about your code
$p *= $n--;
return fact($n, $p);
} else {
return $p;
}
}
Ты на самом деле мутируешь два переменные здесь один выражение. Это умно, если вы пытаетесь сделать код более коротким, но на самом деле есть еще лучший способ.
function fact($n, $p = 1) {
if ($n > 1) {
$p *= $n--;
// just compute the next values; no need to update $p or $n
return fact($n - 1, $p * $n);
} else {
return $p;
}
}
Теперь нам не нужно думать о том, как $p
а также $n
изменить индивидуально. Мы просто знаем, что мы называем fact
снова с следующий значения для каждого состояния $p
а также $n
,
Имейте в виду, что эти принципы настолько сильны в некоторых функциональных языках программирования, что переназначение переменных нравится $p
а также $n
даже не разрешено
Наконец, мы должны поговорить о вашей утечке API, $p
, Если кто-то должен был указать значение при вызове fact
они могут получить неправильный ответ или вызвать ошибку
// bad !
fact(5, 10); // => 1200
Это возможно только потому, что $p
на самом деле выставлен в публичном API. Чтобы обойти это, у вас есть несколько вариантов
Один из них — сделать так, как предлагает @RonaldSwets:
function fact($n) {
// 1 is the base case, like you had for $p in your code
if ($n == 0)
return 1;
// otherwise return $n times the next value
else
return $n * fact($n - 1);
}
Другое — использовать вспомогательную функцию, предназначенную только для личного пользования.
// function used by `fact`
function fact_aux ($n, $p) {
if ($n == 0)
return $p;
else
return fact_aux($n - 1, $p * $n);
}
// function meant to be used by others
function fact ($n) {
return fact_aux($n, 1);
}
Потому что если if
состояние true
Тогда нет return
Заявление когда-либо встречается. Возможно, вы имели в виду это:
if ($n > 1) {
$p *= $n--;
return fact($n, $p); // return the value
}
Вы пытаетесь присвоить переменную, которую вы не передали по ссылке. Либо передать $ p по ссылке (&$p
) или используйте возвращаемое значение. В этом случае возвращаемое значение намного лучше.
Во-вторых, $n--
это пост-декремент, означающий, что ваш код не так хорошо читается.
function fact($n) {
if ($n == 0) return 1;
return $n * fact($n - 1);
}
var_dump(fact(5))
вы на самом деле возвращаете значение только тогда, когда $n == 1
, когда $n > 1
, вы должны вернуть значение fact(n-1)
в fact(n)
,