Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

エラー処理について #304

Open
FineArchs opened this issue Aug 2, 2023 · 32 comments
Open

エラー処理について #304

FineArchs opened this issue Aug 2, 2023 · 32 comments
Labels
enhancement New feature or request

Comments

@FineArchs
Copy link
Member

普通にthrow catchを実装してもいいですが、「エラー型」の実装ができそうなので提案します。

エラー型について

次のようなものを考えています。

  • 何らかの式の評価でエラーeが発生したとき、通常の値の代わりにこの「エラー型」の値Error(e)を返す。
  • 「エラー型」の値は通常の値のように、変数に代入したり関数の引数や返り値にすることができる。
  • 「エラー型」の値は通常の値とは違い、その値を参照して何か計算をしようとするとエラーを発生させる。そのエラーは最初の式の評価で発生したエラーeである。
  • 値が「エラー型」であるかはCore:typeを使用して見分けることができる。これにより例外処理を行う。

#11@syuilo さんが言っていたことを、既存のAiscriptコードの動作を壊さない範囲で実装する案です。

@syuilo
Copy link
Collaborator

syuilo commented Aug 2, 2023

このエラー型の概念って他の言語にあったりしますか?

@salano-ym
Copy link
Member

Either?

@FineArchs
Copy link
Member Author

エラーを関数の返り値として表現している点ではEitherと似ていると思います。
ですが今回のエラー型は演算の対象となった瞬間にAiscript エラーで処理を停止させるため、Eitherのように成功とエラーを同列に扱うようなことはできません。

@FineArchs
Copy link
Member Author

@syuilo 同じ概念を持つ言語に心当たりはありません。
単に #282 で言う「null以外の何かを返す」ためのものとしての発想です。

@salano-ym
Copy link
Member

Core:typeだけ特別でそれ以外は専用メッセージを出す?
そうでないなら単に型エラーで済む気がする

@FineArchs
Copy link
Member Author

型エラーだと原因が分かりにくいので…

@FineArchs
Copy link
Member Author

FineArchs commented Aug 3, 2023

Core:typeだけ特別でそれ以外は専用メッセージを出す?

その通りです。 専用メッセージというか、これまでに出していたエラーと同じメッセージ(index out of rangeやNo such variableなど)を出します。

@salano-ym
Copy link
Member

「null以外の何かを返す」が目的ならエラーチェックしないのはnull参照と同じで自己責任だと思う

@salano-ym
Copy link
Member

普通の1 + "a"みたいな式でもErrorを返すということ?
だとしたら強制終了が遅延されるのはかえって分かりにくいような気もするかも?

@FineArchs
Copy link
Member Author

強制終了が遅延されるのはかえって分かりにくい

それはその通りです
ただCore:typeでの分岐を出来るようにするためにはそうせざるを得ないので…
基本的には計算した値はすぐ何かに使うと思うので、問題は軽いと思っています

@FineArchs
Copy link
Member Author

「null以外の何かを返す」が目的ならエラーチェックしないのはnull参照と同じで自己責任だと思う

ごめんなさい、これよく分かってないです。解説希望です

@salano-ym
Copy link
Member

「null以外の何かを返す」が目的ならエラーチェックしないのはnull参照と同じで自己責任だと思う

ごめんなさい、これよく分かってないです。解説希望です

Json:parseで失敗した返値がError(e)だったとしてこれを特別に扱う必要は無いと思う

@FineArchs
Copy link
Member Author

Json:parseで失敗した返値がError(e)だったとしてこれを特別に扱う必要は無いと思う

次回参照された時にエラーメッセージを出す機能の話でしたら、まあ無くてもいいかもしれませんがあったほうが便利かなと思っています。

@FineArchs
Copy link
Member Author

FineArchs commented Aug 3, 2023

普通の1 + "a"みたいな式でもErrorを返すということ?

とりあえずはモナドのように失敗可能性のある処理にだけErrorを返させようと思っています。

@salano-ym
Copy link
Member

復帰可能(Json:parse)ならError、できない(1+'a')なら強制終了で区別した方がいいと思う。詳しくないけどGoがそんな感じらしいので。
err+1みたいになってエラーが出るのはチェックしなかったことが問題なので普通の型エラー。
Error型を組み込みで入れるのは良いと思う。

@FineArchs
Copy link
Member Author

1+'a'のような事前回避が容易なエラーはその場で強制終了にするのは賛成ですが、復帰可能性の概念は曖昧で基準にしづらい気がします。何故Json:parseが復帰可能で1+'a'やゼロ除算は復帰不可能なのかよく分かりません。

err+1のような事態で単純な型エラーにせずerrに内包されたエラーを出すのは、出来るだけ今まで同様にエラーを出したいという意図があります。(更新履歴を頻繁に確認する習慣がない人は、急に訳の分からない型エラーが出たら途方に暮れてしまうと思います)
とはいえ、これだと先で言われていたような「エラーの発生が遅延されてかえって分かりにくくなる」問題が発生してしまいます。そこで、例えば

number expected but got error. Error Message: "Unexpected end of JSON input"

のような複合のエラーメッセージを出すのはどうでしょうか?

@ikasoba ikasoba added the enhancement New feature or request label Aug 30, 2023
@marihachi
Copy link
Contributor

基本的にはその場でエラーを発生させて、ユーザーの選択(専用の構文を使うなどして)でError型の値を返すようにするのはどうでしょう

try catchのように呼び出し元でのエラーキャッチができないと思います。これが少し気になりました

@FineArchs
Copy link
Member Author

try {
  someFunc()
} catch(e) {
  processError(e)
}

でやりたいことは基本的に

let result=someFunc()
if (Core:type(result) == 'error') processError(result)

で出来るはずなのでその問題はないと思います。

@marihachi
Copy link
Contributor

できないは違いました
ifで分岐、returnしてエラーを呼び出し元に伝える必要があるということですよね

@FineArchs
Copy link
Member Author

エラーを例外ではなく返り値の型で表すことの利点の一つは(静的型チェックを行うシステムであれば)エラーの種類まで含めて型システムが働くことであり、try-catch文が混ざるとこの利点が消えてしまいます。

また、もう一つの利点は(静的型チェックがあれば)プログラマにエラーの処理を強制出来ることなので

ifで分岐、returnしてエラーを呼び出し元に伝える必要がある

これがむしろ利点になります。

(現状は静的型チェックがないのでただ面倒になっているだけですが…)

@FineArchs
Copy link
Member Author

せめて

result? //if Core:type(result) == 'error' return result else result
catch(result) {...} // if Core:type(result) == 'error' {...}

みたいなシンタックスシュガーは用意すべきかも…?

@marihachi
Copy link
Contributor

基本的にはその場でエラーを発生させて、ユーザーの選択(専用の構文を使うなどして)でError型の値を返すようにするのはどうでしょう

これについてはどうですかね?
エラーを処理しなかった場合にエラーの発見が遅れることを防げると思います。ユーザーが後でエラーを処理すると意思表示したときにだけエラーの発生を遅延させます。

@FineArchs
Copy link
Member Author

throw-catchの話ではなく、基本的にはその場で実行を停止するようにしたいという話ですか?

@marihachi
Copy link
Contributor

エラー処理するまでもなくとりあえず動けば良いというようなスクリプトの使い方もあると思ってます。
この場合はエラーがその場で起こって欲しくないですか?

@FineArchs
Copy link
Member Author

エラーを型で表す方式は厳格な型システムを前提としているので、「とりあえず動けば良いというようなスクリプトの使い方」とは思想が真っ向から対立するんですよね…

@salano-ym
Copy link
Member

現状の使い方からするとメッセージ付きのnull-1みたいな感じなので専用構文を挟まないとエラー処理できないのは分かりにくい気がします。
挟ませるとしてどの時点で停止扱いになってどの時点までに挟む必要がありますか?

@marihachi
Copy link
Contributor

marihachi commented Oct 7, 2023

専用構文でエラー処理を宣言するだけで厳密なエラー処理しようとしている書き手の意図は確認できますね
その場合はエンジン側によるエラー停止はしないで良いんじゃないかと思います。
いつまでのエラー処理しないといけないという制約もあるのが理想ですが、実装が複雑になりそうです。

@FineArchs
Copy link
Member Author

話を遡りますが、 @saki-lere さんの言っていた「復帰不可能な」エラーとは、「事前回避可能な」エラーをそう呼んでいるという認識で正しいでしょうか?
そうであれば、そのようなエラーを即時停止の扱いにする理由が分かってきた気がします。(型システムに組み込むと型チェックが複雑になりすぎる)

@FineArchs
Copy link
Member Author

@marihachi という訳で、エラーを「即時停止するエラー」と「処理すべきエラー」に分けようと思うのですが、どうでしょうか?

@marihachi
Copy link
Contributor

例えば、以下のような2種類を分けるということですかね
型違いの四則演算などエラー処理でなんとかするべきではないもの(常に即時エラー)
JSONパースのような入力の違いによってエラーが起こりうるもの(エラー処理可能)

これについては賛成です

@FineArchs
Copy link
Member Author

それでなんですが、そもそも入力の違いや外部要因によって起きるエラーだけを処理可能にするのであれば、そのようなエラーに即時停止のオプションをつける旨味は小さいと思うのですが、いかがでしょうか?

@marihachi
Copy link
Contributor

marihachi commented Oct 8, 2023

処理に失敗した時の値ってことですよね
即時停止は無しでいいと思います

Rustだったら、Resultって仕組みがあって成功失敗を返すとかあったり
C#だったらTry系メソッドで成功失敗をboolean型の戻り値を返して成功だったらoutパラメータから値を取得できるとか
おそらく、その辺の類の機能ですよね。

これまでの話で概ね理解できました
この機能について賛成です

@marihachi marihachi removed the enhancement New feature or request label Oct 13, 2023
@salano-ym salano-ym added the enhancement New feature or request label Feb 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants