これまでに眺めてきた個人的にお気に入りな技術ブログ「その Swift コード、こう書き換えてみないか」もひと通り終わった感じになるようで、残すところは発表資料からは省いたところになるようです。このあたりもおもしろそうな話題がありそうですので、気になるところを眺めていってみることにしますね。よろしくお願いします。
———————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #278
00:00 開始
00:53 UIKit に関する話題も楽しそう(後回し)
01:53 Result とエラーハンドリングの相互変換
02:34 Result 型とは
03:32 Result 型は正否に着目
04:31 get というメソッド名に違和感
06:57 最近は get という名前も見かけるらしい
08:12 見慣れればそれで良いのかもしれない?
09:59 なぜ Result.get はメソッドなのだろう
11:43 get
で計算型感を醸している?
12:26 添字構文で値を取得するアイデアは微妙
12:57 callAsFunction で実現してみる?
15:21 callAsFunction の利用場面
19:21 インスタンス自体がアクションを意味しているときに便利
20:26 callAsFunction の直接実行も可能
21:08 簡潔な反面、情報不足が否めない感じも
22:14 いちばん get() が妥当かもしれない?
23:37 callAsFunction も使いどころによっては良さそう
————————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #278
はい、では始めていきますね。引き続きこのブログでは、Swiftコードをどう書き換えてみるかということを田中亮香さんが提案しています。このブログの基本的な内容は全て見終わったみたいです。ここからは発表資料には載せなかった内容や、少し雑談的な話題になるかと思いますが、せっかくなので色々見ていきましょう。
UIキットに触れるにあたって、ノッピーさん(名前が曖昧ですが)という方が書かれた内容についても見ていくと面白いかもしれません。Swiftと直接関係があるかは分かりませんが、Swiftの視点で見ていくのも良いですね。
イベントで省略した内容についても触れていくといいかもしれません。今回はリザルトスロー関数の総合変換について話していきます。リザルト型はSwiftの劣化型で、まずはリザルト型について少しおさらいしておきましょう。
リザルト型は、Result
という名前で標準ライブラリに定義されています。例えば、Result<Success, Failure>
と書くと、成功時の値がSuccess
、失敗時のエラーがFailure
になります。この定義を使うと、次のように書けます。
enum Result<Success, Failure: Error> {
case success(Success)
case failure(Failure)
}
次に、リザルト型の使用例について見ていきます。例えば、何かの処理を行ってそれが成功するか失敗するか分からない場合には、リザルト型を使います。以下はその具体例です。
func fetchData(completion: (Result<Data, Error>) -> Void) {
// ネットワーク通信などの処理
}
このように、リザルト型で返すことにより、成功時と失敗時のハンドリングを明確にすることができます。
リザルト型の利用に際して、get
かvalue
どちらを使うべきかといった議論もあります。どちらを選ぶにしても、それぞれに利点があります。ただ、get
の方が最近よく見かけるので、こちらを選ぶことが多いです。get
を使うと、成功時は値を取得し、失敗時はエラーを投げるようなメソッドになりやすいからです。
例えば、以下のように使います。
let result: Result<String, Error> = .success("Hello, Swift!")
switch result {
case .success(let value):
print("Success with value: \\(value)")
case .failure(let error):
print("Failure with error: \\(error)")
}
また、Result
がプロパティとして使えない場合、メソッドとして定義することがあります。その場合、func get()
のように書きますが、特に困難なことはありません。
これまで話したように、リザルト型の選択は開発者の好みにも影響されます。どちらでも一長一短あるため、自分が分かりやすいと思う方法を選べば良いでしょう。
以上で、今日の内容についての説明は一通り終わりです。時間がある限り、さらに深掘りしていきたいと思いますので、何か気になる点があればどんどん質問してください。 以前にバッククォート(`)を使った必要性がありましたよね。文脈によってキーワードを分析するという話も興味深いですね。最近登場したコンシューミングという概念でも使われていますが、Swiftでは昔からこのアプローチを採用しているのでしょうか。搭載しやすくて良いですね。
こういった操作は選択回数を増やすといいますか、便利な機能です。ただ、微妙な点もありますよね。コンピューテッドプロパティのようなものが出てきて、これがゲッターを意識しているのかという疑問もあります。
サブスクリプトも面白いアイデアです。引数を取らずに値を返すようにすることで、通常の括弧を使って操作できるようになり、便利です。
英語でダイナミックコーラブル(@dynamicCallable
)という特性を使うと、メソッドを1つ追加するだけで機能できるものがありました。C++でも関数呼び出しをインスタンスに対して行うことで、状態を保持するという技がありましたが、Swiftでも似たようなことができますね。
移動や操作を簡単にするために、インスタンスを関数として扱うことができるのは便利ですが、その応用例は具体的にはわからないこともあります。それでも、ブログなどを通して知識を深めることは有益です。
通常の実装では冗長に感じることもありますが、関数型プログラミングのように実行のタイミングをコントロールできれば、もっとスムーズに行える場合もあるでしょう。リクエストの実行なども同様に、引数を渡すことでメソッドを呼び出すという流れができると思います。そのため、リクエストに対しても簡潔に実行できる方法が求められることがあります。 エクセキュートを呼ぶとか、そういう具体的な方法について話すよりも、リクエストの内容がわからなくなることがあります。そんなときには yield
を使うと良いでしょう。なるほど、こういった関数を @callAsFunction
やパラメーターを持ったりオーバーロードしたりできると、かなりパワフルです。これは面白いと感じましたね。
ドキュメントの関連情報を先に見てみました。納得できる部分もありますね。例えば @callAsFunction
についてですが、dismissAction
というストラクトがあります。この dismissAction
を呼び出すことで、dismissAction()
みたいに書けます。インスタンス自体がアクションを意味しているときには、それを直接呼ぶほうが良いという利用法です。
確かに、この方法だと呼び出し方が微妙だという気持ちもわかりますね。@callAsFunction
を実装することで、インスタンスを関数として呼び出せるようになります。例えば、リザルトもそれ自体でリザルトを得るという意味で関数として呼ぶ感じになります。無理やりかもしれませんが、こういった使い方もありでしょう。リザルトから何かをゲットするという考え方もでき、その場合は誤解が少ないですね。
get
メソッドで受け取るのが無難な気がしてきましたが、ここが微妙ですね。value
はありだと思いますが、Result
の value
が何を意味するかという点も考えると、get
が無難に思えてきます。
@callAsFunction
も関数っぽくない場合がありますので、肩書きが違ってきますね。無理やりな感じですが、使い勝手は悪くないかもしれません。ディスミスポイントの良い例があるので、しっかり抑えることができれば、むしろ良い利用法かもしれません。
今回はディスミスと似たような感じでしたから、まあまあオッケーですね。次回はスロー監査との相互変換について見ていきましょう。今日はこれで終わりにします。