递归函数没有return任何值

Recursive function does not return any value

我想了解为什么这个函数没有 return 任何东西。

function fact($n, $p = 1) {
    if ($n > 1) {
        $p *= $n--;
        fact($n, $p);
    } else {
        return $p;
    }
}

var_dump(fact(5)); // NULL

因为如果 if 条件是 true 那么就不会遇到 return 语句。也许你的意思是:

if ($n > 1) {
    $p *= $n--;
    return fact($n, $p); // return the value
}

您尝试分配一个您没有通过引用传递的变量。通过引用传递 $p (&$p) 或使用 return 值。在这种情况下,return 值更好。

其次,$n-- 是 post 递减,这意味着您的代码读起来不太好。

function fact($n) {
    if ($n == 0) return 1;
    return $n * fact($n - 1);
}

var_dump(fact(5))

你实际上只有 return 值 $n == 1 时。当 $n > 1 时,你必须 return 值 fact(n-1) in fact(n).

递归是一种来自函数式语言的循环结构。所以是的,正如其他人指出的那样,您的函数无法正常工作,因为 if 语句的 true 分支没有 return 任何内容。但是,我对你的代码有额外的评论

function fact($n, $p = 1) {
    if ($n > 1) {
        // this makes it hard to reason about your code
        <b>$p *= $n--;</b>
        return fact($n, $p);
    } else {
        return $p;
    }
}

您实际上是在 one 表达式中改变 two 变量。如果您想让代码看起来更短,这很聪明,但实际上还有更好的方法。

function fact($n, $p = 1) {
    if ($n > 1) {
        <del>$p *= $n--;</del>
        // just compute the next values; no need to update $p or $n
        return fact(<b>$n - 1</b>, <b>$p * $n</b>);
    } else {
        return $p;
    }
}

现在我们不必考虑 $p$n 是如何单独变化的。我们只知道我们用 next 值再次调用 $p$n.

的每个状态

请记住,这些原则在某些函数式编程语言中非常强大,甚至不允许重新分配 $p$n 等变量。


最后,我们必须谈谈你的 API 泄漏,$p。如果有人在调用 fact 时指定一个值,他们可能会得到错误的答案或触发错误

// bad !
fact(5, 10); // => 1200

这是可能的,因为 $p 实际上暴露在 public 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);
}