2017-04-09 56 views
7

也許我真正的問題是「這是否適合學習Perl 6」?基於Should this Perl 6 CATCH block be able to change variables in the lexical scope?,似乎最簡單的例子可能超出了一個簡單的例子。我什麼時候需要恢復Perl 6異常?

在那個問題中,我正在處理一些對於特定問題而言似乎愚蠢或者更好的東西,因爲我正在玩特性而不是解決問題。

有警告的記錄使用作爲特殊類型的異常(「控制異常」),你得到的消息,可以捕捉它,如果你喜歡,但也可以忽略它,它會自行恢復(雖然我是這在Where should I catch a Perl 6 warning control exception?中相當愚蠢)。

除此之外,我正在考慮調用者可以處理被調用者範圍之外的失敗的事情。例如,重新連接到數據庫,修復丟失的目錄以及被調用者沒有責任的其他外部資源問題。

在閱讀其他語言的這類內容時,建議主要是不使用它們,因爲在「真實世界」編程中,人們往往不會真正處理問題。

C# exception handler resume next的答案似乎是說這是不好的做法和醜陋的代碼。我當然還沒有想到在被調用者中隱藏一堆代碼的方法。

我砍掉了這個例子,雖然我不相信這是一個很好的方法來做它或推薦給初學者。該程序在啓動時查找PID文件。如果它找到一個,它會拋出一個異常。處理該異常將檢查其他實例是否仍在運行,這可能會引發不同類型的異常。而且,還有一個可以處理文件IO問題。訣竅是X::MyProgram::FoundSemaphore可以恢復,如果其他程序沒有運行(但留下PID文件)。

+1

對於這個問題不重要,但請注意'BEGIN'在編譯時運行。模塊在安裝時編譯,因此放置在模塊中的代碼可能不會完成預期的工作。 'INIT'對於程序啓動似乎是一個更好的選擇,並且在模塊情況下可以正常工作。 –

+0

是的,INIT似乎更好。 –

回答

6

可恢復的異常肯定不是東西,我發現自己深遠的Perl 6中我使用他們在「用戶空間」的代碼在所有但我不認爲。一個可恢復的例外結果是實現emit函數的正確方法,在supplyreact塊中使用。 gather中使用的take函數也使用可恢復的異常實現,並且 - 如您已經發現的那樣 - warn使用它們。

我懷疑最後一個 - warn - 是典型的Perl 6用戶感興趣的唯一情況。捕獲警告並將它們發送到其他地方 - 可能是日誌文件或日誌服務器 - 是一個相當合理的事情需要做。就學習Perl 6而言,這可能是可恢復異常的一個明顯有用的例子。

我認爲所有利用Perl 6中的可恢復異常的用例本身都被歸類爲「控制異常」是很重要的。控制異常在執行級別上基本上是正常的異常:它們涉及非本地控制轉移。他們在語言級別上做出不同的,因爲這將是比較尷尬的,如果你的emittakewarnnextlast使用Perl 6等等停止,因爲一個CATCH塊的一個default吞嚥控制異常的工作!

但是,它也有點像我說的那樣做,而不是像我這樣做:雖然Perl 6很樂意使用異常系統來實現非本地流量控制,但它在一個滿是灰塵的角落的語言,而不是把它當作一件事情的例子。出於好的理由:通常情況下,使用異常來執行流量控制的代碼很難遵循,而且對於可恢復的異常來說,這是雙倍的。另一個很大的風險是,這種例外情況可能被代碼所吞噬,代碼使用的是tryCATCHdefault--這使得它在更大的代碼庫中變得相當脆弱。

我想象一下,可恢復異常的最佳用途將成爲用戶根本不會考慮異常的實現策略 - 就像takeemit(和,大部分時間,warn)。並且,與現有的可恢復異常的例子一樣,恢復的事件將是一種異常類型,其被專門設計爲在可恢復的情況下拋出,並且僅在這是明智的情況下才被使用。但是,直到Perl 6提供了一種定義自定義控件例外的方式,我寧願不願意這樣做;吞嚥問題使得它太脆弱了。

+0

使用$ * ARGFILES遇到壞文件的可恢復異常的用例:https://stackoverflow.com/questions/48865412/how-should-i-handle-perl-6-argfiles-that-c​​ant-be-read逐線 –

相關問題