我想了解为什么这个函数不会返回任何内容。
function fact($n, $p = 1) {
if ($n > 1) {
$p *= $n--;
fact($n, $p);
} else {
return $p;
}
}
var_dump(fact(5)); // NULL
答案 0 :(得分:3)
因为如果Activesheet.Range(ActiveSheet.PageSetup.PrintArea).Select
条件为Activesheet.Range(ActiveSheet.PageSetup.PrintArea).CheckSpelling
,则不会遇到if
语句。也许你的意思是:
true
答案 1 :(得分:3)
您尝试分配一个未通过引用传递的变量。通过引用传递$ p(&$p
)或使用返回值。在这种情况下,返回值更好。
其次,$n--
是后递减,意味着你的代码读得不好。
function fact($n) {
if ($n == 0) return 1;
return $n * fact($n - 1);
}
var_dump(fact(5))
答案 2 :(得分:2)
递归是一种来自函数式语言的循环结构。是的,正如其他人所说,你的函数无法正常工作,因为if
语句的 true 分支并没有返回任何内容。但是,我还有关于您的代码的其他评论
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);
}
答案 3 :(得分:1)
你的事实只在' Loop through the list of table definitions.
For Each tblRep In dbRep.TableDefs
Set rec1 = dbRep.OpenRecordset("SELECT MSysObjects.Name FROM MsysObjects WHERE ([Name] = '" & tblRep.Name & "') AND ((MSysObjects.Type)=4 or (MSysObjects.Type)=6)")
If rec1.EOF Then
XF = 0
Else
XF = 1
End If
' Ignore system tables and CMDB tables.
If InStr(1, tblRep.Name, "MSys", vbTextCompare) = 0 And _
InStr(1, tblRep.Name, "CMDB", vbTextCompare) = 0 And _
XF = 0 Then
' Open a recordset for the new table.
Set rstNew = dbNew.OpenRecordset(tblRep.Name, dbOpenTable)
' Open a recordset for the old table.
Set rstRep = dbRep.OpenRecordset(tblRep.Name, dbOpenTable)
' Continue if there are records.
If Not rstRep.BOF Then
' Move to the first record.
rstRep.MoveFirst
' Loop through all the old table records.
Do Until rstRep.EOF
' Add a record to the new table.
rstNew.AddNew
' For each field in the new table, set the value
' to the value in the related field of the old table.
For intC = 0 To rstNew.Fields.count - 1
rstNew.Fields(intC).Value = _
rstRep.Fields(rstNew.Fields(intC).Name).Value
Next
' Update the new table.
rstNew.Update
' Move to the next old table record.
rstRep.MoveNext
Loop ' rstRep
End If
' Close the new recordset.
rstNew.Close
' Close the old recordset.
rstRep.Close
End If
Next tblRep
时返回值。在$n == 1
时,您必须在$n > 1
中返回值fact(n-1)
。