SiriまでやってるPokémon GO
本稿が読者の皆さんに届くころにはXcode 8とSwift 3も正式リリース間近

米国版および豪国版のリリースは7月6日。前回執筆時にはすでに同国で社会現象となっていましたが、

こういうのも何ですが、
どうしてPokémon GOは先行者たちが超えられなかったキャズムを超えられたのでしょうか?
個々の要素技術が、
そう。Swift。型推論、
もう1つ似ているのは、
そしてこれが一番大事だと筆者が感じているのは、
変わらないために変える
ポケモントレーナーの視点からあらためてSwift 3を見てみると、++--
演算子やC-styleのfor
の廃止は、
API:旧弊は進化の証
その一方、
var a = [0]
a.append(1) // [0, 1]
a.appendContentsOf([2,3]) // [0, 1, 2, 3]
Swift 3ではこうなっています。
var a = [0]
a.append(1) // [0, 1]
a.append(contentsOf:[2,3]) // [0, 1, 2, 3]
Swiftはもとから
var a = [0]
a += [1]
a += [2, 3]
わかりやすさも、
真偽値を返すAPIは必ずis
を付けるというのも同様で、
import Foundation
var u = NSURL(fileURLWithPath: #file)
if u.fileURL {
print(u.path!)
}
import Foundation
var u = NSURL(fileURLWithPath: #file)
if u.isFileURL {
print(u.path!)
}
ラベルも脱Objective-C
SwiftがObjective-Cの祖先であることを最も感じさせたのは、
func volume(x:Double, y:Double, z:Double)->Double {
return x*y*z
}
という関数は、
volume(2, y:3, z:4) // 24.0
最初のラベルだけ省略されるというわけですが、
volume(x:2, y:3, z:4) // 24.0
のほうがずっとわかりやすいですよね。
ちなみに_
を付ければよいので、
func volume(_ x:Double, _ y:Double, _
z:Double)->Double {
return x*y*z
}
volume(2, 3, 4) // 24.0
「戻り値を捨てる」も明示
「コンパイラーが推論できる場合は推論」
func plusOne(_ i: Int) -> Int {
print(i)
return i + 1
}
_ = plusOne(0) // 1
「_
に代入する」@discardableResult
修飾子で関数側で
@discardableResultfunc plusOne(_ a: Int) ->
Int { print(a) // side effect! return
a+1}plusOne(x)````
var引数禁止
Swift 2までは、var
をつけることで次のようなコードを書くことができました。
// 最大公約数
func gcd(var a: Int, var _ b: Int) -> Int {
a = abs(a); b = abs(b)
if (b > a) { (a, b) = (b, a) }
while (b > 0) { (a, b) = (b, a % b) }
return a
}
これがSwift 3では廃止されるので、
func gcd(_ a: Int, _ b: Int) -> Int {
var (x, y) = (abs(a), abs(b))
if (x > y) { (x, y) = (y, x) }
while (y > 0) { (x, y) = (y, x % y) }
return x
}
一見不便に思えるのですが、inout
という引数もあって、
- 指定なし:
let
と同様。イミュータブル var
:ミュータブルだが、呼び出し元は変更されない inout
:ミュータブルかつ呼び出し元も変更される
という状態だったのが、
UnsafePointer nullability
C APIとの連携ではUnsafePointer
が大活躍するのですが、
let ptr : UnsafeMutablePointer<Int>? = nil
ptr?.memory = 42
型推論もOptional指向に
たとえば次のコードをご覧ください。
func f(value : Int!) {
let x = value + 1 // x: Int - force
unwrapped
let y = value // y: Int? let array = [value, 42]
let array2 = [value!, 42] // [Int] use(a)
}
array
の型は[Int]
なのか[Int?]
なのか。このような場合Swift 3では[Int?]
よりに推論して、[Int]
にします。
where節
プロトコル指向プログラミング
anyCommon([1], 0..<2) // true
anyCommon([2], 0..<2) // false
違う型同士でも、
func anyCommon<T: SequenceType, U:SequenceType
where T.Generator.Element:Equatable,
T.Generator.Element == U.Generator.Element
>(lhs: T, _ rhs: U) -> Bool {
for l in lhs {
for r in rhs {
if l == r { return true }
}
}
return false
}
要は<>の中身が長過ぎるのですが、
func anyCommon<T: Sequence, U: Sequence>(_lhs: T, _ rhs: U) -> Bool
where T.Iterator.Element:Equatable,
T.Iterator.Element == U.Iterator.Element {
for l in lhs {
for r in rhs {
if l == r { return true }
}
}
return false
}
Generic Type Aliasing
Swiftのtypealias
は実に便利な機能ですが、typealias Foo = Bar
はできて、typealias Foo<T> = Bar<T>
ができないのは実に不自然でしたが、
typealias StringDictionary<T> = Dictionary<String, T>
typealias DictionaryOfStrings<T : Hashable>= Dictionary<T, String>
typealias IntFunction<T> = (T) -> Int
typealias Vec3<T> = (T, T, T)
typealias BackwardTriple<T1,T2,T3> = (T3, T2, T1)
プログラムの進化、プログラマの進化
0x20代もあますところ1年となった中年プログラマにとって、
来月以降も、
本誌最新号をチェック!
Software Design 2022年9月号
2022年8月18日発売
B5判/
定価1,342円
- 第1特集
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識 - 第2特集
「知りたい」 「使いたい」 「発信したい」 をかなえる
OSSソースコードリーディングのススメ - 特別企画
企業のシステムを支えるOSとエコシステムの全貌
[特別企画] Red Hat Enterprise Linux 9最新ガイド - 短期連載
今さら聞けないSSH
[前編] リモートログインとコマンドの実行 - 短期連載
MySQLで学ぶ文字コード
[最終回] 文字コードのハマりどころTips集 - 短期連載
新生「Ansible」 徹底解説
[4] Playbookの実行環境 (基礎編)