評估和死亡

這是處理異常的內建方法,而不依賴於像 Try::Tiny 這樣的第三方庫。

my $ret;

eval {
  $ret = some_function_that_might_die();
  1;
} or do {
  my $eval_error = $@ || "Zombie error!";
  handle_error($eval_error);
};

# use $ret

我們濫用die 具有錯誤返回值的事實,並且整個程式碼塊的返回值是程式碼塊中最後一個表示式的值:

  • 如果 $ret 被成功分配,那麼 1; 表示式是 eval 程式碼塊中發生的最後一件事。因此 eval 程式碼塊具有真值,因此 or do 塊不會執行。
  • 如果 some_function_that_might_die() 做了 die,那麼在 eval 程式碼塊中發生的最後一件事就是 die。因此,eval 程式碼塊具有錯誤值,並且 or do 塊確實執行。
  • 必須or do 區塊做的第一件事是閱讀 $@。這個全域性變數將儲存傳遞給 die 的任何引數。|| "Zombie Error" 後衛很受歡迎,但在一般情況下是不必要的。

這一點很重要,因為有些並非所有程式碼都通過呼叫 die 而失敗,但無論如何都可以使用相同的結構。考慮一個返回的資料庫函式:

  • 成功影響的行數
  • '0 but true'如果查詢成功但沒有行受到影響
  • 0 如果查詢不成功。

在這種情況下,你仍然可以使用相同的習語,但你必須跳過最後的 1;,這個函式必須是 eval 中的最後一個。像這樣的東西:

eval {
  my $value = My::Database::retrieve($my_thing); # dies on fail
  $value->set_status("Completed");
  $value->set_completed_timestamp(time());
  $value->update(); # returns false value on fail
} or do { # handles both the die and the 0 return value
  my $eval_error = $@ || "Zombie error!";
  handle_error($eval_error);
};