递归函数没有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);
}
我想了解为什么这个函数没有 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);
}