iPhone Xの購入
本稿を読者のみなさんがお読みになるのは年末年始ですが、その1月前の執筆現在、今年出る予定のApple製品は、HomePodが延期されてあますところiMac Proだけとなりました。最大の目玉であるiPhone Xも、品不足で来年になるかと危惧したものの、筆者の手元に届いており(写真1) 、animojiがはかどっております(図1 ) 。
写真1 iPhone Xラインナップ
図1 animoji
iPhone Xと言えばホームボタンがなくなったことと、「 全画面-顔面センサー=鬼ディスプレイ」のほかにも、本体価格がついに$1,000の大台に乗ったことも話題となりました。ストレージ256GBの上位機種にいたってはMac Bookとほとんど値段が変わりません。それだけの価値はあるのでしょうか?
できることを列挙するのであれば、MacBookはiPhoneの足元にも及びません。iPhoneなら単体で接続できるLTEネットワークに接続するのにMacBookはほかのスマートフォンの力をテザリングで借りなければいけませんし、Face IDはおろかGPSさえ非搭載。カメラにいたってはビデオ会議用のしょぼいインカメラだけです。
しかし、MacBook――というよりMac――でなければできないことが1つ残っています。それがアプリケーションの開発。iPhoneの登場以来ずっと「そういうものだ」と思われてきましたが、その理由がハードウェアの能力不足でないことはiPadとSwift Playgroundsがすでに証明しています(図2 ) 。むしろXcode for iPadがまだないことのほうが不思議なぐらいです。
図2 Swift playgrounds
まだiOSデバイスはおろかMacにIntel入っていないころからApple製品と付き合ってきた筆者からすると、この状況は少々物足りない。さすがに電源を入れたらBASICインタプリタが立ち上がり、プログラムを打ち込まなければ使えない8ビットCPUの時代に戻れとは思いませんが、かつてあったHyperCard(図3 )に相当するものがiPhoneにないことには少なからぬ物足りなさを感じています。
図3 なつかしのHyperCard をiPhone Xで
HyperCardの何が画期的だったかと言うと、プログラミングとオーサリングの境界をなくしたこと。データとコードが渾然一体となった「スタック」は、「 製品」にするには滅法不向きでも、「 動的コンテンツ」としてみた場合には最高で、それこそTwitterにつぶやく程度の気軽さでスタックを作っていたものです。
そのころよりコンピュータができることは飛躍的に増えました。市場も幾何級数的に大きくなりました。しかしそのことがかえってプログラミングというものの敷居を上げたのだとしたらなんと寂しいことでしょう。
筆者がSwiftを「買った」理由の1つは、ますます敷居が上がっていくようにも見えるプログラミングという行為を、「 玄人」をも納得させつつ「素人」に少しでも取り戻そうとした点にあります。スマートフォンにしかできないことがこれだけ増えた今、そろそろPlaygrounds for iPhoneが欲しくなってきませんか?
Swift 4.1
前置きはこれくらいにして、本題に。Xcode 9とともにSwift 4が来たと思いきや、Swift 4.1 の足音がすでに聞こえてきています。Swift 4.0とソースコード互換ではありますが、バイナリ互換ではない点は注意を要します。
正式リリースは来年前半とのことですが、すでにバイナリースナップショットが公式サイトより配布されており、それを使って変更点および新機能を検証できるようになっております。本記事では Ubuntu 16.04用のスナップショットで検証を行いました。
[SE-0157]:再帰的なプロトコル制約
Swift 4.1の一番の目玉はこれでしょう 。プロトコル中のassociatedtype
の制約に、それ自身が使えるようになります(リスト1 ) 。
リスト1 associatedtypeの利用方法の変更
protocol Sequence {
associatedtype Element
associatedtype SubSequence: Sequence
where SubSequence.Element == Element,
SubSequence.SubSequence == SubSequence
// ...
}
protocol Collection: Sequence
where Self.SubSequence: Collection {
// ...
}
筆者から見てSwiftの一番の欠点は、再帰型でした。たとえばSwift 1では、
enum List<T> { // Swift 2 or better
case Nil
indirect case Cons(T, List<T>)
}
のように、自分自身と同じ型のプロパティを内包した型さえ作れなかったのです。この状況はSwift 2で大きく前進したのですが、あくまで再帰的な型を作れるのは実体型であり、プロトコルで同様なことはできませんでした。
ご覧のとおり実例としてSwiftで欠かすことのできないSequence
とSubSequenc
eが挙げられており(リスト1) 、これもたバイナリ非互換の一因かと思われますが、これらのプロトコルは今までどおり使えるのでソース互換は保たれていると認識しています。
メモリ管理をどうするかは実体型の問題であってプロトコルの問題ではなかったはずですが、Swift 4時点でリスト2 のコードは問題なく動いていました。
リスト2 バージョンアップで動かなくなると予想されるコード
class A {}
protocol P {
weak var weakVar: A? { get set }
unowned var unownedVar: A { get set }
}
Swift 4.1以降は警告が発せられ、Swift 5からはエラーになります。
リスト3 で、Swift 4.1ではストアドプロパティがすべてEquatable
の場合には==
演算子が、Hashable
の場合には加えて.hashValue
が自動で定義されるようになります(図4 ) 。
リスト3 .hashValueの自動生成
struct Point<T:Hashable>: Hashable {
let x: T
let y: T
init(_ x: T, _ y: T) {
self.x = x
self.y = y
}
}
図4 実行結果
Point(3, 0) == Point(0, 3) // false
Point(3, 0) == Point(3, 0) // true
Point(3, 0).hashValue // -2942920663782199421
Protocol Extensionの導入により自動生成される演算子やメソッドやプロパティは格段に増えたのですが、この2つがまだ自動生成の対象になっていなかったのはよく考えてみると意外です。==
はストアドプロパティがすべて==
のときだけtrue
で、hashValue
はストアドプロパティの.hashValue
を合成すれば生成できるというのはいわば自明だからです。
もちろんこれまでどおり手動で定義されたものはそちらが優先されるので、4.1が正式リリースされたら==
と.hashValue
は削除してしまうのも一考かもしれません。==
はとにかく.hashValue
で適切なハッシュ関数を定義するのは案外難易度高いので。
次回予告
前半で昨今のプログラミング環境の敷居の高さをぼやきつつ、後半でプログラミング言語の詳細を紹介するというのは我ながら本末転倒感がありますが、次回はもう少しカジュアルに行く予定です。
第1特集
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識
第2特集
「知りたい」「 使いたい」「 発信したい」をかなえる
OSSソースコードリーディングのススメ
特別企画
企業のシステムを支えるOSとエコシステムの全貌
[特別企画]Red Hat Enterprise Linux 9最新ガイド
短期連載
今さら聞けないSSH
[前編]リモートログインとコマンドの実行
短期連載
MySQLで学ぶ文字コード
[最終回]文字コードのハマりどころTips集
短期連載
新生「Ansible」徹底解説
[4]Playbookの実行環境(基礎編)