Re:(個人的に) ここが好きだよ!Swift (愛好会)

  • 22
    Like
  • 0
    Comment

気づいたらもう僕の担当日になったんですね。Swift 関係の Advent Calendar に空きがないか探すのがまるで昨日の出来事みたいなのに。

と言うか僕そもそも Swift 愛好会に参加してない気がするのですが本当に大丈夫ですかね?えっ?ダメ?仕方ない書くのやめましょうか(おいこら

というわけで Swift 愛好会に参加してないはずなのに記事予約しちゃった理由は上記通り、Swift 関係の Advent Calendar の空きを探してたら見つかったのがここだったわけです。どうか温かい目で見守ってください。それがダメなら今から飛び込み入会させてください(笑)

でも予約したのはいいものの、正直結局何を書くべきか、全くのノープランです。すみません。最近 Watch Dogs 2 にハマってて。あれやっぱりプログラマなら一度やるべきゲームだと思うんですよ。別にゲーム内でプログラミングするわけじゃないが。

そして本来はもっとこう技術的というかコード的な話をしようと思ってたのですがなんかここそういう空気じゃないみたいだし、かと言って先週末皆さん行ってきた合宿がとても楽しいようで何よりですが自分参加してないしそれに絡む何かを書くのもできません。悔しい。

そんな中で、昨日会社の忘年会で上司にこんなこと聞かれたわけですよ。

上:プログラミング経験何年くらい?
僕:学校では趣味で Visual Basic とか C とか Cuda とか独学でちょっとくらい触ったけど、本格的にやり始めたのはやはり入社した後 Swift 出てからですね(状況説明すると僕そもそもプログラマとして入社したわけじゃないので社内では僕のプログラミング経験なんて知ってる人たぶんほとんどいないw)
上:やはり Swift はいいの?
僕:そうですね関数の引数にラベル付けられたりぬるぽを未然に防げたり結構いいと思います

とまあそんな他愛のないような会話ですが、やはりいきなり Swift は何がいいのと聞かれると、頭の中では大好きなのにすぐには整理できずスラスラと答えられないのがとても悔しいです。まるで好きな子に告白しても「じゃあ私のどこが好きなの」って聞かれても頭が混乱して「え〜あ〜」しか答えられない DT のように。

そこですかさず @Yu-taro さんの記事をスパッと出せるくらいの頭の回転が欲しいです。

さて前振りがあまりにも長くなりすぎたのでそろそろ本題に入ります。Swift のどこがいいの、をもう一回改めて振り返ってみる記事です。@Yu-taro さんの記事を振り返りながら自分なりの追筆を語らせてください。

返答部

型が厳格
兎にも角にもこれが1番
厳格と言っても、Objetive-CのNSStringとNSMutableStringのような分離はしていないこともよい
少し前に賑わっていたnull安全も、型がしっかりとしていることがベースになっている気がする
必ずしもnull安全がすべてを解決してくれる訳ではないが、Objective-Cを使っていた頃より明らかに楽できるようになった
Swiftは型に始まり、型に終わると言ってもいいと思う

強い静的型付言語の特徴ですね。これ自体は Swift 独自の特徴ではありませんが、そのおかげでより安全のコードが組めるのは確かです。そしてその上に成り立つ Optional 型こそが Swift の大本命と言っても過言ではないでしょう。

ところが型付けの流れの歴史を振り返ってみるととても面白いことになります。初期の頃、まあ C とかが主流の頃(さすがに C より以前は筆者の実力不足で語れませんが)はハードウェアのスペック制限上、型は基本静的型付けでした。ただでさえコンパイルに時間かかるからコンパイラーに余計な作業押し付けたくなかったでしょう。もちろんチェックとかにも時間費やしたくないから型の互換もできます。弱い型付です。そう int a = 0; printf("%lf\n", a) のような、int 型なのに long float 型として使っちゃうことだって可能な世界です。それも暗黙な型変換なんざ黒テクノロジーのない普通の使い方です。まあ C 言語の基本思想は「プログラマは正しい」「プログラマがやるっつったらやる」ですから文法ミスさえなければ何でもやってくれる(やらせてくれる)純粋ないい子ですからね。きっと黒髪ショートが似合うロリな子です(嘘

そして時が流れ、ハードスペックがどんどん上がってきてコンパイル時間がもうボトルネックじゃない時代に突入しました。プログラミング言語の黄金期なんじゃないですかね。いろんなプログラミング言語がいろんなところから生まれてきました。まさにプログラミング言語戦国時代。(まあ今でも新しい言語がどんどん発明されてきているわけですが。)そして今度はプログラマたちはもうハードの制限に縛られてくない。もっといろんなことを自由にやりたい。「プログラマに、自由の翼を」。そこで動的型付けが流行りだしました(登場自体はもっと昔からすでにありましたが)。"10" + 10 なんてことも平気でやらせてくれる。型は全て実行時に行うものですから。

ところが最近になってまた静的型付けが王座を奪い返しに来ました。コンパイル時の最適化もしやすいし、ハードウェアスペックが上がって型推論もすぐできるようになって動的言語と同じくらい描きやすいし、何より動的言語より静的言語の方が実行時の安全性が担保しやすいです。設計思想が「プログラマとは間違いを犯すもの」に変わりましたね。この設計思想の変化の流れは、僕の中では Swift が Objective-C と真逆な強い静的型付けを採用したこと自体以上に面白いと感じています。

Switchがかなり強力
break 書かなくていいのはかなり好き
Castもできる書き方も好き

let any = 1 as Any`
let int: Int = {
    switch any {
    case let intValue as Int: return intValue
    case let stringValue as String: return Int(stringValue) ?? 0
    default: return 0
    }
}()

Enumとの組み合わせやPatternMatchと用途が広いので、用法用量を守ることが大切だとは思う

Swift の switch 文は本当に強力です。しかもパターンマッチを採用しているので、自分でカスタマイズすることだって可能です(~= をオーバーライドすればすぐできる)

そして何より一番嬉しいのは、全パターンをカバーできてない場合はエラーとしてコンパイルさせてくれないこと。前にも言った「プログラマは間違いを犯すもの」の思想が、ここにも垣間見できますね。

ただ唯一の switch 文に関して微妙に不満というか違和感を覚えているのは、まあ C family を引き継いでるから何の躊躇もなく switch 文の最後は default キーワードが使われていますが、多くの場合それは例外処理なのに default よりも else の方が意味的に正しい気がするんですよな…

関数型が使える
一時変数を置いたりすることなく、簡潔に処理することが可能になり、気持ちいい
慣れるまでは違和感があったが、一旦覚えるとを組み合わせて解決できないか考えるようになった
個人的には reduce が使えるとヨッシャ•̀.̫•́✧

関数型プログラミングは今までやったことなかったので、Swift で初めて触った時本当に新鮮でした。C とか Cuda の時代にコツコツ for 文回して配列から別の配列作る時の作業は何だったのかと。

まあ map ももちろん強力ですが flatMap も使い方によってはとても便利ですね。ただ reduce に関しては強力すぎて何でもかんでもできちゃうから reduce 使わなくていい場面はなるべく reduce 使わないほうがいいのでは?と思ったり。少なくとも let a = [1, 2, 3]; let b = a.reduce([]){$0 + [$1 * 2]} みたいなコードよりも明らかに let a = [1, 2, 3]; let b = a.map{$0 * 2} のほうがわかりやすいし見やすいので reduce が強力だからといって濫用しては行けないと思います。

ちなみに最初の最初は「何で map って単語使ってるんだろ」って悩んだことありました。地図じゃないのに。ところがよくよく考えてみたら気づきました。節子、それ地図とちゃう、「マッピング」や。

言語自体のアップデートが早い
(これは賛否両論あるとは思うが)

開発が早いだけでなく、負債や変更の影響度を考慮しつつ、よくしていこうという意図が感じられる
swift-evolution のProposalを追っていくだけでも楽しめる
毎日知らないことを知れてとてもいい

これはいい意味でも悪い意味でも、Swift はまだ誕生して間もないとても若い言語だからこそのことですね。言語作った当初あまり十分に考慮できていないものは素早く切り捨てられたり置き換えられたりして、より良い言語に日々進化を遂げているのは間違いありません。例えば最初の最初の範囲演算子は ..... が使われ、前者は最後の数字が含まれない半開区間、後者は最後の数字も含まれる閉区間を表し、まあなんとなくわからなくもないがたまたま Ruby のあれとちょうど逆になってプログラマたちを戸惑わせたのもまた今となって懐かしいエピソードですが(もちろん今はご存知の通り前者は ..< に変更されより直感的でわかりやすい演算子になりました)、Swift 3.0 ではさらに今まで IntervalRange 二つあった範囲を表すものを全部 Range に統合し、結果的に RangeClosedRangeCountableRangeCountableClosedRange になり、範囲に対する扱いがより厳密になりさらに安全性を高めたのです。もちろん逆に言うと新参メンバーにとってサンプルコードを一つ手に取っても Swift のバージョンの違いで動かなかったりエラーになったりすることも多々あるからその点すでに安定している C++ などとは大違いですね。幸いなことに、3.0 は最後の大きな破壊的変更(最後の破壊的変更とは言ってない)を含むメジャーバージョンアップになります(なるはず)。

コミュニティが活発
各所で勉強会が活発!!!!!
勉強会後の繋がりもあることが多い
try!Swiftのような世界規模のカンファレンスがある
(後発言語の中では珍しいのでは)

これは本当にとても大きいですね。言語のシェアこそせいぜい 2% 程度しかない(TIOBE 2016 年 12 月調べ)のに、Qiita での Swift タグ付き記事数がとっくに 6000 を超えてます(全てが有用だとは言えないが)(以下記事数は全て投稿時 2016 年 12 月 7 日現時点のものです)。その点、Swift の 2 倍のシェアを持つ Python でも記事数が 8000 程度であり、さらに Swift 登場した 2014 年 6 月以降の新規記事を限定すると 7000 記事程度になります。また Swift の 1.5 倍のシェアを持つ C# と比べるとさらに悲惨な結果に。なんと投稿時間を限定しなくても C# タグ付きの記事はわずか 2000 程度しか有りません。同じ「大手商業企業主導」の言語なのにこの差である。ちなみに 17% のシェアを誇るランキングダントツ 1 位の Java の記事数もわずか 5000 程度と Swift 以下です。ちなみに僕が調べた限り、主流言語の中で唯一 Swift の記事数 / シェア率を超えているのは、Swift と同等なシェアを持つ日本生まれの Ruby(2014 年 6 月以降の新規投稿は約 8000 記事)です。さすが本場。強い。

ちなみにコミュニティーの活発性について一つ追筆させてください。各所の非公式(アップル主導ではないという意味)な勉強会やカンファレンスだけでなく、公式コミュニティーも非常に活発です。先ほどにも言いました Swift の switch 文の default キーワード問題、実はこれ昨日恐れ恐れ Swift Evolution のメーリングリストにこれについて聞いてみました。「やはり else にしませんか」って。そしたらとても暖かい返事をいただきました。似たような議論がすでに去年に一度あったにもかかわらず、だ(まあ去年のあの提案はそもそも default キーワードを廃止しようぜという提案なので微妙に違うっちゃ違うが)。もちろん結果としては去年のあれと同じ、すでに広く普及されている C family の言語との一致性を保つために default キーワードを変更する予定はないとのことですが、ただその幾つかある返信の中で一つわざわざ switch 文における default の意味を親切に教えてくださったメールもありました:

Perhaps you're thinking about this choice of syntax from a different angle than was intended. default is not literally meant to be a "default value" or, in most cases, "the default case", rather a "default pattern"; a place for control to flow given no other option.

意訳:おそらくこの default という単語をちょっと違った(間違った)角度から見てるのではないかと。default はここでは「デフォルト値」、もしくは「デフォルトケース」などの意味ではなく、むしろ「デフォルト(フローにおいて何の指定もない)パターン」を意味しています。

なるほど、これで少しだけ納得がいきました(全部とは言えないが)。今まではどっちかというと case default のような意味で考えてたからとても違和感を覚えたのだ。この単語はそこまでの深い意味はなく、ただたんに何もないパターンを指しているだけなのだ。

まあそれでもやはり場合によって(特に default で例外処理している時)多少なりとも違和感を覚えることはありますので、そういった場合は case _ で書こうと思ってます。

質問に答えてくれる土壌がある
(コミュニティにも付随しますが)

答えてくれる方々が多い
Twitter
Slack
etc...
アーキテクチャ等を議論、相談したもできる
(社内にiOSアプリエンジニアがほぼ自分1人なので、社外に聞ける人たちがいるのは、個人的に非常にありがたい)

僕も社内に iOS エンジニアは僕一人しかいない(まあコンシューマーゲーム屋だからしゃーない)のでとてもわかります。困ったことがあれば Google や Qiita で調べれば大体のことはなんとかなります。それくらい皆さんとてもアクティブで記事をいっぱい残しています。そして勉強会など参加してとても熱い方々ばかりで大変 Swift のやり甲斐を感じます。

追伸部

@Yu-taro さんの記事には書いてありませんでしたが、実は僕個人としてやはり一番気に入っているのは「ラベル付き引数」です。null 安全(まあ Swift は厳密には null 安全なんて言葉ないしそもそも null じゃなくて nil だから正しくは「Optional 型」だけどまあそんなの伝わればいいから)以上にこちらが好きです。いやもちろん null 安全も好きですが。

「ラベル付き引数」というのは、関数やメソッドを宣言するときに、引数の引数名とは別に「ラベル」をつけることができるという機能です。そしてこのラベルを設定することによって、関数やメソッドを利用するときに、通常引数名がなくなり、変数だけ当てはめばいい文法がラベルを書かなくてはいけないことになる機能です。Swift のソースコードでいうとこのようなことです:

func insert(_ x: Int, to array: inout [Int], at i: Int) {
    array.insert(x, at: i)
}

ここで、insert が関数名で、xarrayi が引数名、そして _toat がそれぞれのラベルとなります(もちろんご存じの通り _ はラベル省略になります)

こうやって書くことによるメリットは何かというと、この insert 関数を使うことにとてもわかりやすいということです:

var members = [3, 5, 7]
insert(2, to: members, at: 0)

こういう風に、とても自然言語に近い構文となっており、ソース解析においてほとんどの場合ドキュメントやメソッド定義まで行かなくても、こう文を読むだけで「ああ members20 番目に追加するんだね」ってわかります。

このラベルという機能がないと、このメソッドは insert(2, members, 0) になってしまいます。さてこれは一体 members0 番目に 2 を追加するのか、それとも 2 番目に 0 を追加するのか、というのはドキュメントかコメントを読むか、ドキュメントもコメントもなければ実装を確認するしかないのです。そして大体我々プログラマはドキュメントとかコメント書くのが嫌いな人間です。えっ?違う?嫌ってるのは僕だけ!?そうかそうか…

ちなみにこの引数ラベル機能は別に Swift 特有のものではありません、そもそも Swift が引き継いでる Objective-C も引数ラベルは当たり前の機能ですし、Objective-C が影響を受けたオブジェクト指向の元祖とも言われている Smalltalk もこの引数ラベル機能(Smalltalk では「キーワード」と呼ぶらしいが)があります。もともと Smalltalk は関数は全て「メッセージ」ですのでとても自然言語寄りな文法になったのではないかと思いますが、それを取り入れた Objective-C は本当に大好きです([] を使うのはちょっと見づらいのは否定しないが…)。最初に僕はプログラマとして入社したのではないと言いましたが、ええ実は僕は最初移植担当のディレクターとして入社したのです。そしてワケあって iOS プログラムのソースも読まなきゃいけなかったのですが、その時感じたのは「あれ?読める… Objective-C 全く勉強したことないのに俺にも読めるぞジョジョ!」だったのです。しかもそのあと自分で勝手にソースコードいじって UI をカスタマイズできる程度のスキルまで手に入れた。全てはその自然言語寄りの英語さえ読めればソースコードもなんとか読める文法のおかげです。引数ラベルに圧倒的感謝。

というわけで、だいぶ遅くなりましたが、Swift 愛好会 Advent Calendar 7 日目の記事を終わらせていただきます。最後までこんなくだらない文章に付き合ってくれてありがとうございます。明日の AWS のお話楽しみにしております。