Skip to content
Playground

エラー

error は、effect として流れる型付きエラーをまとめて宣言する短縮構文である。

宣言

yulang
pub error fs_err:
    not_found path
    denied path
    invalid_path path

この一行で次のものがまとめて生成される。

  • pub enum fs_err — variant は not_found path / denied path / invalid_path path
  • pub act fs_err — variant と同名の operation を持ち、戻り値は never
  • impl Throw fs_errtype throws = '[fs_err]our e.throw を持ち、 対応する operation を発火する。
  • impl Display fs_err — 既定の文字列化(手書きの impl で上書き可能)。
  • fs_err::wrap — companion module 内のヘルパー。error effect を result 値に閉じる。
  • fs_err::up — companion module 内の handler。他の error 型が from fs_err を宣言している場合、narrower error を fs_err の effect に 持ち上げる。

constructor と operation は同名

variant 名は データ構築子と effect operation の両方 として使える。 文脈で必要な側が選ばれる。

yulang
my err: fs_err = fs_err::not_found path    // 値として構築
fs_err::not_found path                       // effect として発火

fail で投げる

fail は prelude の prefix 演算子で、e.throw を透過的に呼ぶ。

yulang
pub prefix(fail) = \e -> e.throw

構築したエラー値を effect として送り出すときに使う。

yulang
my read_text path = fs::read_text path

推論型は概ね path -> [fs; fs_err] str の形になり、エラーが effect row に 明示される。

名指しで捕まえる

catch の effect arm は、operation 名を直接書いてエラーを捕まえる。

yulang
catch fs::read_text path:
    fs_err::not_found _, _ -> "(missing)"
    fs_err::denied _, _ -> "(denied)"
    value -> value

Yulang のエラー設計は 常に名指しで捕まえる ことを前提にしている。 Display を実行時に dispatch して任意のエラーを文字列化するような型消去の ラッパー(いわゆる anyhow 的なもの)は意図的に採用していない。各エラーは effect row の中で常に具体的な名前で見え、発火地点と捕捉地点が型から分かる。

wrap:値に閉じる

yulang
my read_text_safe path = case fs_err::wrap: fs::read_text path:
    result::ok text -> text
    result::err err -> err.show

E::wrap は、引数 thunk が起こす対応 error effect を捕まえて result _ E を返す。Efrom エントリがある場合、wrap はリンクされた narrower error も同時に捕まえ、生成された Cast impl 経由で wrap する。

from による集約

yulang
pub error io_err:
    fs from fs_err
    parse from parse_err

これにより次のものが生成される。

  • variant io_err::fs fs_errio_err::parse parse_err
  • Cast fs_err -> io_errCast parse_err -> io_err の impl
  • fs_errparse_err も同時に捕まえる拡張版 io_err::wrap
  • narrower error を io_err effect に変換する handler io_err::up
yulang
my read_and_parse path =
    io_err::up:
        my text = fs::read_text path            // [fs_err]
        parse_json text                         // [parse_err]
    // block 全体の effect は [io_err]

基礎的な変換機構については Casts を、catch と effect row の 全般的な話は Effects を参照。

Yulang