SiriまでやってるPokémon GO
本稿が読者の皆さんに届くころにはXcode 8とSwift 3も正式リリース間近[1]、(i|mac|tv| watch)OSもバージョンが上がり、もしかしてiPhone 7と次期MacBook Proすらリリースされているかもしれません。そんな大事な時期ですが、しかしPokémon GOをスルーするわけには行かないでしょう。何しろSiriまでやってるんですから(図1)。
米国版および豪国版のリリースは7月6日。前回執筆時にはすでに同国で社会現象となっていましたが、ポケモンのふるさとでもある日本での正式リリースは脱稿直後の7月22日。で、筆者もやってみると……見事にはまってしまいました。Apple Watch入手後も「わっかが1周」することなどほとんどなかった筆者が1日も欠かさずムーブゴールを達成するどころか(図2)、1日平均10km以上歩いてます(図3)。いったい何が起きたのでしょうか?(図4)
こういうのも何ですが、Pokémon GOを成立させている各要素に目新しい点はまるで見当たりません。ポケストップは開発元のNianticが2012年からやっていたIngressの援用。ポケモンにいたっては1996年、20年前リリースの「初代」の151種類そのまま。3DグラフィックスはUnityですし、サーバはGCPやAWSといった「お馴染み」のクラウドプラットフォーム。AR? セカイカメラなら2008年に始まって2013年に終了していますが、何か?
どうしてPokémon GOは先行者たちが超えられなかったキャズムを超えられたのでしょうか?
個々の要素技術が、先行者たちを超えてなかったからだというのが筆者の答えになります。ポケモン20年。スマホ10年。トレーナ、もといユーザは「やって」なくても「知って」はいたわけです。「新しい」のに「慣れている」。これって何か心当たりありませんか?
そう。Swift。型推論、オプショナル、プロトコルといったSwiftをSwiftをたらしめている要素は、どれ1つとってもほかの言語で実装されていたものばかり。しかしそれが1つにまとまると今までになかった何かになる。その結果、みんなが使うようになる……。
もう1つ似ているのは、リリース時には未完成で、今もなお未完成であること。本原稿執筆現在、ポケモンには欠かせない機能であるはずのモンスター交換はいまだに実現されていませんし、2016年のアプリとは思えないほど強制終了しまくりですし、ポケストップとジムの配置は今もなお試行錯誤が続いています。おかげで中の人はまだLv5みたいではありますが、全世界の人を歩かせるにはそれで十分だったのです。
そしてこれが一番大事だと筆者が感じているのは、細やかな報酬の重要性。人――というのが主語が大き過ぎるのであれば少なくとも筆者――は、いきなり10km歩けと言われても微動だにしないのです。しかし100mごとにポケストップがあると、いつの魔(間)にか10km歩いてしまっている。水族館のイルカやアシカのショーではショー全体が終わったあとではなく一芸ごとに餌を与えていますが、実は人というケダモノもそうなのです。大きな報酬がまとめて支払われるその日まで我慢に我慢を重ねられる人は偉大ですが、小さな人まで動いて初めて世の中は動くことを、Pokémon GOがあらためて示してくれたと感じています。
変わらないために変える
ポケモントレーナーの視点からあらためてSwift 3を見てみると、変わらないために変えているのだという思いを新たにします。とくに前回紹介した++--
演算子やC-styleのfor
の廃止は、「Cにおもねる新言語」から「Swiftという一人前の言語」への進化だと言い切ってよいでしょう。ところでポケモンの弊害に「進化」という言葉の「誤用」があります。生物学的には同一個体の変化は「進化」ではなく「変態」なのですが、英語でもmetamorphoseではなくevolveですし、こうなるともはや誤用ではなく「語彙の進化」だと筆者も諦め気味。Xcodeでは2のコードを3に進化させられるのですが、アメ玉が不要な点はPokémon GOより優れてます:-)
API:旧弊は進化の証
その一方、一見するとなんではじめからそうしなかったという変更も多々見られます。たとえばAPIの命名規則ですが、Swift 2ではこうだったのが……、
Swift 3ではこうなっています。
Swiftはもとから「名前が同じでもシグネチャが異なれば別の関数」なのですから、はじめからSwift 3のようにすればよかったのにと思わぬでもないですが、その一方進化前のSwiftはObjective-Cだったことを考えれば、生まれたての段階ではObjective-Cを引きずっているのも自然ではあります。余談ですが、演算子を使った記法ではSwift 2とSwift 3の違いはありません。
わかりやすさも、非英語圏まで考慮すると演算子を使ったほうが直感的なような気がします。
真偽値を返すAPIは必ずis
を付けるというのも同様で、Objective-Cではそうなっていなかったのですね。
ラベルも脱Objective-C
SwiftがObjective-Cの祖先であることを最も感じさせたのは、ラベルの扱いかもしれません。たとえば、
という関数は、Swift 2ではこう呼び出します。
最初のラベルだけ省略されるというわけですが、これはわかりづらい。
のほうがずっとわかりやすいですよね。
ちなみに「呼び出し時にラベルを省略する」のであれば、Swift 2もSwift 3も同様に_
を付ければよいので、ラベルの省略は関数定義時に明示するというのは癖にしておいてよいでしょう。
「戻り値を捨てる」も明示
「コンパイラーが推論できる場合は推論」以上に「明示すべき場合は明示」というのがSwiftismですが、関数をサブルーチンとして使う場合、つまり戻り値を使わない場合にも明示するようになりました。
「_
に代入する」ことで「戻り値不要」を示しているわけです。Swift 2でも実は有効です。Swift 3では、@discardableResult
修飾子で関数側で「戻り値捨ててもOK」を指定することもできます。
var引数禁止
Swift 2までは、関数の引数にvar
をつけることで次のようなコードを書くことができました。
これがSwift 3では廃止されるので、上記のコードは次のように書き直す必要があります。
一見不便に思えるのですが、その一方Swiftにはinout
という引数もあって、
- 指定なし:
let
と同様。イミュータブル
var
:ミュータブルだが、呼び出し元は変更されない
inout
:ミュータブルかつ呼び出し元も変更される
という状態だったのが、1つ減ることで紛らわしさがずいぶんと軽減されます。
UnsafePointer nullability
C APIとの連携ではUnsafePointer
が大活躍するのですが、これが明示的にOptionalとなることで、次のようなコードが安全に書けるようになります。
型推論もOptional指向に
たとえば次のコードをご覧ください。
array
の型は[Int]
なのか[Int?]
なのか。このような場合Swift 3では[Int?]
よりに推論して、明示的にUnwrapされている場合のみ[Int]
にします。
where節
プロトコル指向プログラミング(POP)では、次のようなコードは可能であるにとどまらず推奨すらされます。
違う型同士でも、同じプロトコルに準拠していれば共通要素があるかどうかを確認できるわけですが、その実装はSwift 2ではずいぶんと長ったらしいものとなっていました。
要は<>の中身が長過ぎるのですが、Swift 3では次のように関数シグネチャの直後に書くことでずいぶんとすっきりします。POPがますますはかどりそうです。
Generic Type Aliasing
Swiftのtypealias
は実に便利な機能ですが、typealias Foo = Bar
はできて、typealias Foo<T> = Bar<T>
ができないのは実に不自然でしたが、やっとDWIM(Do what I mean)になります。
プログラムの進化、プログラマの進化
0x20代もあますところ1年となった中年プログラマにとって、Pokémon GOがあらためて示したあまりにまっとうな世界観にあらためて自省しています。一言で言えば、「千里の道も楽しく一歩から」。「千里の道も一歩から」だけだと大業は苦行の積み重ねという感じがしますが、一歩が苦しいなんて誰が言ったのでしょう。一歩一歩が楽しかったからこそ、気がつけば千里を踏破したのではないのか。プログラミングもまたその例外ではないように感じます。1行1行が楽しかったからこそ今まで続いてきたのだと。そしてそれが楽しかったのは、楽しむための工夫をどこかでしてきたからではないのか、と。
来月以降も、また一緒に歩いていきましょう。一歩ずつ、楽しく。
- 第1特集
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識
- 第2特集
「知りたい」「使いたい」「発信したい」をかなえる
OSSソースコードリーディングのススメ
- 特別企画
企業のシステムを支えるOSとエコシステムの全貌
[特別企画]Red Hat Enterprise Linux 9最新ガイド
- 短期連載
今さら聞けないSSH
[前編]リモートログインとコマンドの実行
- 短期連載
MySQLで学ぶ文字コード
[最終回]文字コードのハマりどころTips集
- 短期連載
新生「Ansible」徹底解説
[4]Playbookの実行環境(基礎編)