omochimetaru
omochimetaru.qrunch.io

SwiftのResult型の提案が改定され、第2レビューが開始した

2018/11/29に投稿

先日記事に書いて紹介した、Result型の提案についてのレビューが終了して、コアチームからフィードバックが出た。

記事: https://omochimetaru.qrunch.io/entries/pkQOWpPfxTfvnUwm

それによると、Result型の導入は認められたが、提案の詳細についてコアチームによる改定が行われて、新たに第2レビューが行われるとのことだ。

改定された提案: https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md

第2レビュースレッド: https://forums.swift.org/t/revised-se-0235-add-result-to-the-standard-library/18371

アナウンスの内容が興味深く、内容も多かったので翻訳した。記事末尾に掲載する。英語は不得意なので気になった点があれば原文を読むこと。

内容としてちょっと意外だったのは、Errorだけself-conformanceする、というアクロバティックな決定がされたことだ。でも確かに、Resultに関してはスマートな選択肢ではある。

現時点のレビューの流れだと、case名をvalue/errorからsuccess/failureに変えたいという意見が目に入るけど、どうなるだろうか。

このまま行けば、先日の記事の予言が当たりそうだ。

微修正のために棄却され、再提出後のレビューで採用される流れになると予想する。


[改定] SE-0235: 標準ライブラリへのResultの追加

John McCall

SE-0235: 標準ライブラリへのResultの追加は改定されました。今から12/2(日)までレビューを行います。 初回のフィードバックに基づいて、コアチームはこの機能をSwiftに追加することは価値があると同意します。 そして、我々による改訂提案へのフィードバックを新たに募集します。 Chris Lattnerが休暇中なので、私がレビューマネージャを引き継ぎます。

初回のレビューに参加してくれたみなさんありがとうございました。そこでのフィードバックは概ね、広く使われて再実装されている型を標準化するというアイデアにポジティブなものでした。コアチームはレビューの中で出てきたいくつかの重要な点を議論しました。

  • いくらかの人たちは、将来のasync/await機構がResultの最も重要なユースケースを無用にするだろうと見込んでいます。コアチームはasync/awaitがこの型の重要性をほとんど無くしそうであることに同意します。しかし、完全に不要にするほどでは無いし、この型はasync/awaitに向けて現場に存在するものを標準化するのに役に立ちます。

  • いくらかの人たちは、optional chainingやその他の構文的なサポートを追加することで、提案がより強力で使いやすくなるだろうと勧めました。コアチームはそうしたサポートが無くともこの型はとても便利で、それは将来の提案で考える事もできると考えました。

  • いくらかの人たちは、ResultEitherに変更して一般化することを勧めました。Either型については過去に多く話し合われていて、それはそれで便利かもしれません。でもコアチームはエラーハンドリングに寄せた型が説明可能性と構造化の力を改善するより良い道だと考えました。例えば、Result型にoptional chainingを適用することは意味が通りますが、一般的なEither型に適用するのはおかしいのは確かでしょう。Result型は現場で広く使われているので、その利便性については多くの前例があります。

提案の詳細については、コアチームは多くの点を支持します。

  • コアチームはmap, flatMap, mapError, flatMapErrpr, unwrappedメソッドの名前と意味を支持します。

  • コアチームは、コミュニティが気にしていた、ErrorジェネリックパラメータがSwift.Error型をshadowすることに、実用上の問題はないと考えます。

  • コアチームは、ResultHashableEquatableに条件付きで準拠したほうが良いと同意します。

コアチームはコミュニティからのフィードバックを統合して、出てきた改善箇所を狭めて、提案を調整するのに多くの時間を使いました。

  • Error型パラメータはSwift.Errorに準拠する制約がなされるべきでしょう。これはこの型の意図された目的を強制し、Swiftの通常のエラーハンドリングと一緒に使いやすくします。またこれは生のエラーコードや文字列よりも意味づけされたenumやラッパー型を使うような、より実践的な良いエラーハンドリングを緩く勧めます。これは将来typed throws機能を追加する可能性を阻害しません。なぜならそうした機能の元でエラー型は明らかにそこでもSwift.Errorに準拠する事を求められるだろうからです。

  • 上記との組み合わせで、Swift.Errorプロトコル型がSwift.Errorプロトコルに準拠するべきでしょう。これは一般にはself-conformanceと呼ばれる言語機能に該当します。これは現在のところ@objプロトコルだけに適用されるように制限されています。コアチームはこの制限を特にSwift.Errorだけ外す事について調査して、そして決定しました。この変更により、上記のようにErrorパラメータがSwift.Errorに制約されていても、Swift.Error型をErrorパラメータとして使えるようになります。これによりエラー型についてジェネリックなコードを書くときのその他の努力がシンプルになります。

  • enumcaseの名前はジェネリック型に揃うように名前を変更したほうが良いでしょう。具体的には下記になります。

public enum Result<Value, Error: Swift.Error> {
    case value(Value)
    case error(Error)
}
  • value(), error(), isSuccess() メソッドは削除したほうが良いでしょう。これらは便利な糖衣ですが、Swiftのすべてのenumに対して自動的に適用できる、より一般的な言語機能として扱ったほうが良いかもしれません。

  • fold()メソッドは削除したほうが良いでしょう。コアチームはこの関数のようなものを含む便利なものがあることに同意しますが、これの最も良い名前を決定する時間を取ったほうが良く、分割した追加の提案として後から追加できます。さらに、foldは本質的にswitch式です。Resultのためにこの特別なバージョンを追加するよりも、一般的な言語機能を単純に追加するほうが良いでしょう。

  • throwをキャプチャするイニシャライザはinit(catching body: () throws -> Value)に名前を変更したほうが良いでしょう。クロージャの代わりに名前付きの関数を使う場合に、これは引数ラベルを与えます。ラベル無しイニシャライザは規約的に変換であり、そしてこれは関数の値を変換するものではありません。

  • ResultCustomDebugStringConvertibleに準拠すべきではないでしょう。デフォルトの挙動が妥当です。

このレビューの初回に参加してくれたみなさん、ありがとうございました。第二回においては、コアチームは概念上この機能の価値を受け入れており、上記で改定した提案についてのフィードバックを特に求めています。すべてのレビューフィードバックはこのフォーラムか、もしプライベートに保ちたければ、私に直接(Chrisではなく)、フォーラムのダイレクトメッセージかシンプルにメールで伝えてください。

(この投稿の多くはChris Lattnerが書きましたが、どんな誤りも私のものです。)

関連記事

コメントはありません。
ブログを開設

クランチで技術ブログを
始めてみませんか?

この先は、クランチへのアカウント登録、及びログインが必要なページになります。

Markdownの書き方
見出し # 見出し(h1)
## 見出し(h2) , ### 見出し(h3) ...
リスト - 箇条書き
   - タブでインデント
番号付きリスト 1. テキスト
2. テキスト
改行 行末に半角スペース2つ
リンクの挿入 [タイトル](https://xxx.com)
引用 > テキスト
コード挿入 ```cpp:title
code
```
画像の挿入 ![代替テキスト](URL "タイトル")
太字 **テキスト**
斜体 *テキスト*
打消し線 ~~テキスト~~
水平線 ***
技術ブログを開設
ログイン