位元詩人 [Raku] 程式設計教學:例外 (Exceptions) 處理

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo 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!";
    }
}
關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。