編程基礎篇 · 綫性結構:你天天在用
棧:Cmd+Z 和「爆棧」的秘密
第二種收納方式長得像一摞盤子:只能從最上面放、也只能從最上面拿,這叫棧。聽着限制很大?可你每天按的撤銷鍵、程式裏每一次函式調用,靠的都是它。這一課先親手玩壞一個文檔再一鍵撤回來,最後圍觀一場「爆棧」事故——全球最大的程序員問答網站 Stack Overflow,名字就是從這場事故來的。
先玩 · 撤銷鍵的真身
左邊是個迷你文檔,用四個按鈕隨便折騰它。留意右邊:你的每一步操作都被壓成一張牌,疊在「操作棧」上——後做的壓在上面。折騰夠了,連按幾下「Cmd+Z 撤銷」,看看它撤的順序。
📄 迷你文檔
隨便操作,別心疼
🥞 操作棧
每步操作壓一張牌,最上面 = 最近一步
(還沒有操作)
發現未?撤銷永遠先撤最近嗰步。這不是產品經理的選擇,是棧的天性:後進先出(LIFO,Last In First Out)。只從頂端拿,最先拿到的自然是最後放的。撤銷要是不按這個順序來——先撤掉十步前的操作——文檔立刻亂成一鍋粥。凡是「按原路退回去」的事,天生就該用棧收納。
程式點樣記得「返到邊」?
你讓 AI「做晚飯」,它做到一半要切菜,切菜切到一半刀鈍了要磨刀……每次「暫停手頭的事去幹別的」,程式都會把當前進度壓進一個棧裏。看下面的動畫(滾到這裏會自動播一遍),留意每個任務完成後,程式是怎麼自動找回上一個任務的。
準備就緒點「播放」或滾動到這裏,看一次完整的調用與返回
這個棧叫函式調用棧,每張牌叫一個「棧幀」,裏面記着「這個任務幹到哪了、幹完回到哪」。程式不需要什麼全局調度員——彈出棧頂,自然就回到了上一層暫停的位置。你學過的 Agent 也一樣:主任務幹到一半發現要先查資料,就把主任務壓棧、先幹子任務,子任務完成彈出,接着幹主任務。
爆棧現場 · Stack Overflow 是怎麼發生的
棧的容量是有限的。下面這個函式自己調用自己(這叫遞歸),左邊是程式碼,右邊是調用棧。先不勾終止條件跑一次,看看會發生什麼;再勾上跑一次對比。
function 倒數(n) {
if (n === 0) return; // 終止條件(保險絲)
列印(n);
倒數(n - 1); // 自己調用自己
}
倒數(5);
💥 Stack Overflow棧溢出,程式崩潰
呢樣同 AI 有咩關係?關係大了。Agent 幹活也是「主任務壓棧、先幹子任務」,那萬一子任務又派生子任務、一層層沒完沒了呢?和沒寫終止條件的遞歸一模一樣——所以所有正經的 Agent 框架都要設最大步數 / 最大深度,超過就強制停下來。那根保險絲,就是給「無限遞歸」上的保險。下次你看到 AI 寫的遞歸程式碼,驗收清單第一條:終止條件在哪?
✅ 這一課想和你分享的
- 棧 = 一摞盤子:只從頂端放和拿,後進先出(LIFO)
- 撤銷鍵的真身:每步操作壓一張牌,Cmd+Z 永遠先彈最近那張
- 函式調用靠棧記路:彈出棧頂,自動回到上一層暫停的地方
- 爆棧 = 只壓不彈:沒有終止條件的遞歸把棧堆滿,程式當場崩潰
- Agent 的保險絲:最大步數限制,防的就是任務棧的「無限遞歸」