初學者撰寫遞迴函數時,常在遞迴呼叫處忘記加上 return,導致函數雖然執行到基底案例並 return 了值,但值無法層層傳回最外層呼叫者,最終得到 null。
<?php
function test($i) {
$i -= 4;
if ($i < 3) {
return $i; // 基底案例:正確返回
} else {
test($i); // ❌ 錯誤:遞迴呼叫未加 return!
}
}
echo test(30); // 輸出:(空白/NULL)
?>
test(30) 呼叫 test(26) → test(22) → ... → test(2)test(2) 滿足 $i < 3,執行 return 2return 2 返回給 上一層的 test(6) 函數內部test(6) 的 else 區塊只有 test($i),沒有接收返回值也沒有 returntest(6) 隱性返回 null 給 test(10),以此類推...test(30) 最終拿到 null<?php
function test($i) {
$i -= 4;
if ($i < 3) {
return $i;
} else {
return test($i); // ✅ 關鍵:加上 return 傳遞返回值
}
}
echo test(30); // 輸出:2
?>
test(30) ──呼叫──▶ test(26) ──呼叫──▶ ... ──呼叫──▶ test(2) ▲ │ │ ▼ ◀────────── return 2 ◀────────── return 2 ◀────────── return 2 (每一層都必須有 return 接住並往上拋)
<?php
function factorial($n) {
if ($n <= 1) {
return 1;
}
return $n * factorial($n - 1); // 乘法運算需接收遞迴結果
}
echo factorial(5); // 120
?>
<?php
function scanDir($path) {
$files = scandir($path);
foreach ($files as $file) {
if ($file === '.' || $file === '..') continue;
$fullPath = $path . DIRECTORY_SEPARATOR . $file;
if (is_dir($fullPath)) {
yield from scanDir($fullPath); // PHP 7+ 生成器委派
} else {
yield $fullPath;
}
}
}
foreach (scanDir('/var/www') as $file) {
echo $file . PHP_EOL;
}
?>
<?php
function debugRecursion($n, $depth = 0) {
$indent = str_repeat(' ', $depth);
echo "{$indent}呼叫 debugRecursion($n)\n";
if ($n <= 0) {
echo "{$indent}基底案例,返回 0\n";
return 0;
}
$result = debugRecursion($n - 1, $depth + 1);
echo "{$indent}接收遞迴結果:$result,返回 " . ($result + 1) . "\n";
return $result + 1;
}
debugRecursion(3);
/* 輸出:
呼叫 debugRecursion(3)
呼叫 debugRecursion(2)
呼叫 debugRecursion(1)
呼叫 debugRecursion(0)
基底案例,返回 0
接收遞迴結果:0,返回 1
接收遞迴結果:1,返回 2
接收遞迴結果:2,返回 3
*/
?>
遞迴函數的返回值必須像「接力賽棒」一樣,每一層都要用 return 接住並往上傳遞。漏寫一層 return 就會斷鏈,導致最終結果遺失。養成「遞迴呼叫前必加 return」的肌肉記憶,並善用除錯輸出觀察呼叫堆疊,能有效避免此類低級錯誤。