Perl 6 程式設計教學:例外 (Exceptions) 處理

PUBLISHED ON JAN 5, 2018 — PROGRAMMING
FacebookTwitter LinkedIn LINE Skype EverNote GMail Email Email

    在實際情境中運行的程式,即使程式本身沒有臭蟲 (bug),仍然要面對許多可能的錯誤 (error) 或例外 (exception)。例如,想要將某個字串轉成數字,但字串本身不是合法的數字;想要讀取某個外部檔案,卻權限不足;想要解析某個 XML 檔案,但該 XML 檔案內有錯誤的格式。我們不能天真地認定程式不會發生錯誤,而要詳細考慮可能發生的錯誤,撰寫相關的程式碼。

    拋出例外事件

    die 是 Perl 5 留下來的語法,後面接一個字串,可以拋出例外事件,見下例:

    1 + 2 == 3 or die "Wrong logic";
    

    有型別的例外事件

    Perl 6 增加有型別的例外事件,主要是為了增加錯誤訊息的可讀性,如下例:

    die X::IO::DoesNotExist.new(:path("foo/bar"), :trying("zombie copy"))
    

    想要使用內建的例外物件,可見官網有關 Exception 類別的說明,此處不逐一列出。

    接收例外事件

    使用 CATCH 區塊可以接住例外事件,可搭配 when,對於不同類型的例外以不同方式處理,如下例:

    die X::IO::DoesNotExist.new(:path("foo/bar"), :trying("zombie copy"));
     
    CATCH {
        when X::IO { say "some kind of IO exception was caught!"; }
        default { say "Something wrong"; }
    }
    

    進入 CATCH 區塊後,會跳出程式,不會再執行後續的程式碼,如下例:

    die "Something happens";
     
    CATCH {
        default { .say; }
    }
    
    say "This won't happen";
    

    加上 .resume 後,可從例外中回復,如下例:

    die "Something happens";
     
    CATCH {
        default { 
            .say;
            .resume;
        }
    }
    
    
    say "This will happen as well";
    

    try

    try 區塊可將可能會發生例外的程式碼包住,引發錯誤後仍可繼續執行程式,如下例:

    try {
        die "Something happens";
     
        CATCH {
            default { .say; }
        }
    }
    
    say "This will happen as well";
    

    throw

    throw 由 Exception 物件呼叫,作用類似於 die。見下例:

    X::AdHoc.new(:payload<foo>).throw;
    "OHAI".say;
    
    CATCH {
        when X::AdHoc { .resume }
    }
    
    "OBAI".say;
    

    自訂 Exception 類別

    除了使用內建的 exceptions 外,使用者也可自訂自己的 Exception 類別,建立 Exception 類別時至少要建立一個回傳字串的 message 方法。以下例子摘自 Perl 6 官網:

    class X::YourApp::SomeError is Exception {
        method message() {
            "A YourApp-Specific error occurred: out of coffee!";
        }
    }