Factor 的錯誤系統由三個部分組成:throw用來拋出錯誤,recover用來處理錯誤,而ERROR:則用來定義你自己的錯誤類型。
throwthrow(位於 kernel 中)會拋出錯誤。它的引數可以是任何值,例如字串、數字或元組,而這個值之後就會成為你可以檢查的錯誤:
! DOCTEST: SKIP
"file not found" throw
throw不會回傳;目前這個詞剩下的部分會被略過。
recoverrecover(位於 continuations 中)是 Factor 的 try/catch。它接受一個try引述和一個recovery引述:
recover ( try recovery -- )
如果try在沒有拋出錯誤的情況下結束,recovery就會被忽略。如果try拋出錯誤,錯誤會被推入堆疊,然後執行recovery:
[ "boom" throw ] [ drop "caught" ] recover .
! => "caught"
[ "ok" ] [ drop "never runs" ] recover .
! => "ok"
when(位於 kernel 中)是它的自然搭檔:只有在堆疊頂端為真值時,它才會執行引述:
: check-positive ( n -- )
0 < [ "negative!" throw ] when ;
ERROR:ERROR:會定義一個元組類別以及一個詞,這個詞會建立全新的實例並將它拋出:
! DOCTEST: SKIP
ERROR: not-found path ;
"/missing" not-found
! throws T{ not-found { path "/missing" } }
沒有 slot 的錯誤只要寫成ERROR: name ;就行,呼叫name會拋出一個空實例。用ERROR:定義的元組帶有一個類別述詞name?,你可以用它來測試攔截到的錯誤是否屬於該型別。
攔截到的錯誤就只是一個元組,因此每個由ERROR:定義的 slot,都和其他元組一樣帶有自動產生的slot>>讀取器。
! DOCTEST: SKIP
{
T{ not-found { path "/a" } }
T{ not-found { path "/b" } }
}
[ path>> ] map . ! => { "/a" "/b" }
Elena 是報紙工廠新上任的品質經理,她請你寫一支小程式來監控生產室。
使用ERROR:這個解析詞來定義錯誤元組類別machine-error。它不需要任何欄位。
machine-error ! throws a fresh machine-error
定義check-humidity。它會從堆疊取出濕度讀數,並在讀數嚴格大於70時throw出字串"humidity too high"。否則它不回傳任何東西。
50 check-humidity ! returns nothing
80 check-humidity ! throws "humidity too high"
定義check-temperature。它會從堆疊取出溫度讀數,並在讀數嚴格大於500時throw出字串"temperature too high"。否則它不回傳任何東西。
400 check-temperature ! returns nothing
600 check-temperature ! throws "temperature too high"
定義monitor,讓它從堆疊取出濕度和溫度,並執行這兩項檢查。如果任何一項檢查拋出例外,monitor應該改為拋出一個全新的machine-error。如果兩項都通過,monitor不回傳任何東西。
50 400 monitor ! returns nothing
80 400 monitor ! throws a machine-error
50 600 monitor ! throws a machine-error
定義monitor-batch,讓它接收一個由{ humidity temperature }讀數組成的陣列,並回傳其中有多少筆會失敗(也就是有多少筆會讓monitor拋出)。
{ { 50 400 } { 80 400 } { 50 600 } { 60 200 } } monitor-batch .
! => 2