SlideShare a Scribd company logo
Swift2.xを
Scalaから見る
1
安達 勇一
クラスメソッド株式会社
2015年11月11日
Ⓒ Classmethod, Inc.
2
安達 勇一
• 2013/12 入社

• TwitterID: @UsrNameu1

• Github: https://github.com/
UsrNameu1

• Blog: http://dev.classmethod.jp/
author/yad

• ここ半年はサーバーサイドメイン
Topics for today
• ミックスイン
• 正格評価・遅延評価
• 変位指定
3Ⓒ Classmethod, Inc.
Topics for today
• ミックスイン
• 正格評価・遅延評価
• 変位指定
4Ⓒ Classmethod, Inc.
ミックスイン
• ミックスイン
• 抽象インターフェイス
• デフォルト実装
• ミックスイン対象制限
5Ⓒ Classmethod, Inc.
ミックスイン
6Ⓒ Classmethod, Inc.
• ミックスイン(mix-in)とは?
クラスが「本来の型」に加えて、なんらかの任意の振
る舞いを提供していることを宣言するために、クラスが
実装する型
Bloch(2008)  Effective Java 2nd edition
ミックスイン
• ミックスイン
• 抽象インターフェイス
• デフォルト実装
• ミックスイン対象制限
7Ⓒ Classmethod, Inc.
抽象インターフェイス(Scala)
8Ⓒ Classmethod, Inc.
• traitは抽象インターフェイスをサポートしている
trait AbstractTrait {
type DataType
val constant: DataType
var variable: DataType
def method(): DataType
}
Scala code
抽象インターフェイス(Scala)
9Ⓒ Classmethod, Inc.
• traitは抽象インターフェイスをサポートしている
trait AbstractTrait {
type DataType
val constant: DataType
var variable: DataType
def method(): DataType
}
抽象型メンバー、定数、変数、メソッドが定義できる
Scala code
抽象インターフェイス(Swift)
10Ⓒ Classmethod, Inc.
• protocolは抽象インターフェイスをサポートしている
protocol AbstractProtocol {
typealias DataType
var constant: DataType { get }
var variable: DataType { get set }
func method() -> DataType
init(t: DataType)
subscript(i: Int) -> DataType { get }
func + (lhs: DataType, rhs: DataType)
-> DataType
}
Swift code
抽象インターフェイス(Swift)
11Ⓒ Classmethod, Inc.
• protocolは抽象インターフェイスをサポートしている
protocol AbstractProtocol {
typealias DataType
var constant: DataType { get }
var variable: DataType { get set }
func method() -> DataType
init(t: DataType)
subscript(i: Int) -> DataType { get }
func + (lhs: DataType, rhs: DataType)
-> DataType
} 抽象型メンバー、プロパティ、メソッド、イニシャライザ
サブスクリプト、演算子が定義できる
Swift code
ミックスイン
• ミックスイン
• 抽象インターフェイス
• デフォルト実装
• ミックスイン対象制限
12Ⓒ Classmethod, Inc.
デフォルト実装(Scala)
13Ⓒ Classmethod, Inc.
• traitはデフォルト実装をサポートしている
trait AbstractTrait {
type DataType = String
val constant: DataType = “aa”
var variable: DataType = “aaa”
def method(): DataType = { “aaaa” }
}
Scala code
デフォルト実装(Scala)
14Ⓒ Classmethod, Inc.
• traitはデフォルト実装をサポートしている
trait AbstractTrait {
type DataType = String
val constant: DataType = “aa”
var variable: DataType = “aaa”
def method(): DataType = { “aaaa” }
}
デフォルトの実装をtraitの各メンバーに対して定義できる
Scala code
デフォルト実装(Swift 2.x)
15Ⓒ Classmethod, Inc.
• protocol extensionはデフォルト実装をサポートしている
extension AbstractProtocol {
typealias DataType = String
var constant: DataType { return “a” }
func method() -> DataType { return “aa” }
}
Swift code
デフォルト実装(Swift 2.x)
16Ⓒ Classmethod, Inc.
• protocol extensionはデフォルト実装をサポートしている
extension AbstractProtocol {
typealias DataType = String
var constant: DataType { return “a” }
func method() -> DataType { return “aa” }
}
デフォルトの実装をprotocolの各メンバーに対して定義できる
Swift code
ミックスイン
• ミックスイン
• 抽象インターフェイス
• デフォルト実装
• ミックスイン対象制限
17Ⓒ Classmethod, Inc.
ミックスイン対象制限(Scala)
18Ⓒ Classmethod, Inc.
• traitは自分型アノテーションで継承の対象になる型を
限定できる
trait AbstractTrait {
self: SomeClass =>
def method(): String = { “aaaa” }
}
Scala code
ミックスイン対象制限(Scala)
19Ⓒ Classmethod, Inc.
• traitは自分型アノテーションで継承の対象になる型を
限定できる
trait AbstractTrait {
self: SomeClass =>
def method(): String = { “aaaa” }
}
Scala code
ミックスインの対象になる型をSomeClassに限定できる
→AbstractTraitはSomeClassと
 そのサブ型からしか継承できない
ミックスイン対象制限(Swift 2.x)
20Ⓒ Classmethod, Inc.
• protocol extensionのSelfへの制約によって
デフォルト実装が使える継承の対象となる型を制限できる
extension AbstractProtocol
where Self: SomeClass {
func method() -> String { return “aa” }
}
Swift code
ミックスイン対象制限(Swift 2.x)
21Ⓒ Classmethod, Inc.
• protocol extensionのSelfへの制約によって
デフォルト実装が使える継承の対象となる型を制限できる
extension AbstractProtocol
where Self: SomeClass {
func method() -> String { return “aa” }
}
デフォルトの実装を使える型はSomeClassとそのサブ型のみ
Swift code
ミックスイン対象制限(Swift 2.x)
22Ⓒ Classmethod, Inc.
• protocol extensionのSelfへの制約によって
デフォルト実装が使える継承の対象となる型を制限できる
extension AbstractProtocol
where Self: SomeClass {
func method() -> String { return “aa” }
}
デフォルトの実装を使える型はSomeClassとそのサブ型のみ
Swift code
See also→
http://www.slideshare.net/UsrNameu1/swift2-protocol-extension
ミックスインのまとめ
23Ⓒ Classmethod, Inc.
Scala Swift
抽象インターフェイス
デフォルト実装
ミックスイン対象型への制約
trait protocol
trait protocol extension
traitでの
自分型アノテーション
protocol extensionでの
Self への制約
Topics for today
• ミックスイン
• 正格評価・遅延評価
• 変位指定
24Ⓒ Classmethod, Inc.
正格評価・
遅延評価
• 正格評価・遅延評価
• lazy修飾子
• 遅延引数
• 遅延コレクション
25Ⓒ Classmethod, Inc.
正格評価・遅延評価
26Ⓒ Classmethod, Inc.
• 評価(evaluation) とは?
式から値を計算し、取り出す操作
正格評価・遅延評価
27Ⓒ Classmethod, Inc.
• 評価(evaluation) とは?
式から値を計算し、取り出す操作
let a = 1 + 1
Swift code
正格評価・遅延評価
28Ⓒ Classmethod, Inc.
• 評価(evaluation) とは?
式から値を計算し、取り出す操作
let a = 1 + 1
1 + 1という式から2を計算し、取り出す
Swift code
正格評価・遅延評価
29Ⓒ Classmethod, Inc.
• 評価(evaluation) とは?
式から値を計算し、取り出す操作
let a = 1 + 1
1 + 1という式から2を計算し、取り出す
a という名前の定数に代入する
Swift code
正格評価・遅延評価
30Ⓒ Classmethod, Inc.
• 正格評価(strict evaluation) とは?
 評価結果が使用されるタイミングに関係なく
 即時に行われる評価のこと
func add(a: Int, _ b: Int) -> Int {
return a + b
}
struct Component {
let c = add(1, 1)
}
Swift code
正格評価・遅延評価
31Ⓒ Classmethod, Inc.
• 正格評価(strict evaluation) とは?
 評価結果が使用されるタイミングに関係なく
 即時に行われる評価のこと
func add(a: Int, _ b: Int) -> Int {
return a + b
}
struct Component {
let c = add(1, 1)
}
cが用いられるタイミングに関係なく
インスタンス生成時に評価される
Swift code
正格評価・遅延評価
32Ⓒ Classmethod, Inc.
• 遅延評価(strict evaluation) とは?
 即時に行われず、後々必要になったタイミングで
 行われる評価のこと
func add(a: Int, _ b: Int) -> Int {
return a + b
}
struct LazyComponent {
lazy var d = add(1, 2)
}
Swift code
正格評価・遅延評価
33Ⓒ Classmethod, Inc.
• 遅延評価(strict evaluation) とは?
 即時に行われず、後々必要になったタイミングで
 行われる評価のこと
func add(a: Int, _ b: Int) -> Int {
return a + b
}
struct LazyComponent {
lazy var d = add(1, 2)
} dが用いられるタイミングで評価される
Swift code
正格評価・
遅延評価
• 正格評価・遅延評価
• lazy修飾子
• 遅延引数
• 遅延コレクション
34Ⓒ Classmethod, Inc.
lazy修飾子(Scala)
35Ⓒ Classmethod, Inc.
• lazyをval(定数)の前につけると遅延評価になる
 
object LazyConstants {
lazy val const: String = {
println("computed")
"constant"
}
}
val a = LazyConstants.const
Scala code
lazy修飾子(Scala)
36Ⓒ Classmethod, Inc.
• lazyをval(定数)の前につけると遅延評価になる
 
object LazyConstants {
lazy val const: String = {
println("computed")
"constant"
}
}
val a = LazyConstants.const
Scala code
宣言時には評価されない
lazy修飾子(Scala)
37Ⓒ Classmethod, Inc.
• lazyをval(定数)の前につけると遅延評価になる
 
object LazyConstants {
lazy val const: String = {
println("computed")
"constant"
}
}
val a = LazyConstants.const
Scala code
宣言時には評価されない
アクセス時に評価され、
computed が出力される
lazy修飾子(Swift)
38Ⓒ Classmethod, Inc.
• lazyをvar(変数)の前につけると遅延評価になる
 
class LazyConstants {
lazy var const: String = {
print("computed")
return "constant"
}()
}
let constants = LazyConstants()
let const = constants.const
Swift code
lazy修飾子(Swift)
39Ⓒ Classmethod, Inc.
• lazyをvar(変数)の前につけると遅延評価になる
 
class LazyConstants {
lazy var const: String = {
print("computed")
return "constant"
}()
}
let constants = LazyConstants()
let const = constants.const
Swift code
インスタンス生成時には評価されない
lazy修飾子(Swift)
40Ⓒ Classmethod, Inc.
• lazyをvar(変数)の前につけると遅延評価になる
 
class LazyConstants {
lazy var const: String = {
print("computed")
return "constant"
}()
}
let constants = LazyConstants()
let const = constants.const
Swift code
インスタンス生成時には評価されない
プロパティアクセス時に評価され、
computed が出力される
lazy修飾子(Swift)
41Ⓒ Classmethod, Inc.
• グローバル変数、定数はlazy修飾子をつけなくても
自動的に遅延評価になる
 
let someConst: String = {
print("computed")
return "constant"
}()
let length = someConst.utf8.count
Swift code
lazy修飾子(Swift)
42Ⓒ Classmethod, Inc.
• グローバル変数、定数はlazy修飾子をつけなくても
自動的に遅延評価になる
 
let someConst: String = {
print("computed")
return "constant"
}()
let length = someConst.utf8.count
Swift code
この時点では評価されない
lazy修飾子(Swift)
43Ⓒ Classmethod, Inc.
• グローバル変数、定数はlazy修飾子をつけなくても
自動的に遅延評価になる
 
let someConst: String = {
print("computed")
return "constant"
}()
let length = someConst.utf8.count
Swift code
この時点では評価されない
アクセス時に評価され、
computed が出力される
正格評価・
遅延評価
• 正格評価・遅延評価
• lazy修飾子
• 遅延引数
• 遅延コレクション
44Ⓒ Classmethod, Inc.
遅延引数(Scala)
45Ⓒ Classmethod, Inc.
• 名前渡しパラメーターは引数の評価を遅延する
 
val assertionsEnabled = true
def byNameAssert(pred: => Boolean) =
if (assertionsEnabled && !pred)
throw new AssertionError
byNameAssert(2 > 5)
Scala code
遅延引数(Scala)
46Ⓒ Classmethod, Inc.
• 名前渡しパラメーターは引数の評価を遅延する
 
val assertionsEnabled = true
def byNameAssert(pred: => Boolean) =
if (assertionsEnabled && !pred)
throw new AssertionError
byNameAssert(2 > 5)
Scala code
assertionsEnabled が真の時
初めて引数 pred を評価する
遅延引数(Scala)
47Ⓒ Classmethod, Inc.
• 名前渡しパラメーターは引数の評価を遅延する
 
val assertionsEnabled = true
def byNameAssert(pred: => Boolean) =
if (assertionsEnabled && !pred)
throw new AssertionError
byNameAssert(2 > 5)
Scala code
assertionsEnabled が真の時
初めて引数 pred を評価する
評価は引数を渡すタイミングではなく、
byNameAssert内部の処理が走るタイミングで行われる
遅延引数(Swift)
48Ⓒ Classmethod, Inc.
• @autoclosureは引数の評価を遅延する
 
func myAnd(
lhs: Bool,
@autoclosure _ rhs: () -> Bool
) -> Bool {
if lhs { return rhs() }
else { return false }
}
let result = myAnd(true, 1 < 2)
Swift code
遅延引数(Swift)
49Ⓒ Classmethod, Inc.
• @autoclosureは引数の評価を遅延する
 
func myAnd(
lhs: Bool,
@autoclosure _ rhs: () -> Bool
) -> Bool {
if lhs { return rhs() }
else { return false }
}
let result = myAnd(true, 1 < 2)
Swift code
lhs が真の時初めて引数 rhs を評価する
遅延引数(Swift)
50Ⓒ Classmethod, Inc.
• @autoclosureは引数の評価を遅延する
 
func myAnd(
lhs: Bool,
@autoclosure _ rhs: () -> Bool
) -> Bool {
if lhs { return rhs() }
else { return false }
}
let result = myAnd(true, 1 < 2)
Swift code
lhs が真の時初めて引数 rhs を評価する
評価は引数を渡すタイミングではなく、
myAnd内部の処理が走るタイミングで行われる
正格評価・
遅延評価
• 正格評価・遅延評価
• lazy修飾子
• 遅延引数
• 遅延コレクション
51Ⓒ Classmethod, Inc.
遅延コレクション(Scala)
52Ⓒ Classmethod, Inc.
• ビューはmap, filter等の変換メソッド処理を
遅延するコレクションを提供する
 
val vectorView = Vector(1 to 5: _*).view
val middleView =
vectorView.map { x => println(x); x * 2 }
middleView.map { _ + 3 }.force
Scala code
遅延コレクション(Scala)
53Ⓒ Classmethod, Inc.
• ビューはmap, filter等の変換メソッド処理を
遅延するコレクションを提供する
 
val vectorView = Vector(1 to 5: _*).view
val middleView =
vectorView.map { x => println(x); x * 2 }
middleView.map { _ + 3 }.force
Scala code
遅延コレクション生成
遅延コレクション(Scala)
54Ⓒ Classmethod, Inc.
• ビューはmap, filter等の変換メソッド処理を
遅延するコレクションを提供する
 
val vectorView = Vector(1 to 5: _*).view
val middleView =
vectorView.map { x => println(x); x * 2 }
middleView.map { _ + 3 }.force
Scala code
遅延コレクション生成
この時点では中の処理は実施されず
中間のVectorも作成されない
遅延コレクション(Scala)
55Ⓒ Classmethod, Inc.
• ビューはmap, filter等の変換メソッド処理を
遅延するコレクションを提供する
 
val vectorView = Vector(1 to 5: _*).view
val middleView =
vectorView.map { x => println(x); x * 2 }
middleView.map { _ + 3 }.force
Scala codeforceメソッドで正格コレクションに戻され、
それまでの変換メソッド処理が実施される。
     (1 2 3 4 5が出力される)
遅延コレクション生成
この時点では中の処理は実施されず
中間のVectorも作成されない
遅延コレクション(Swift 2.x)
56Ⓒ Classmethod, Inc.
• LazySequenceプロトコルはmap, filter等の変換
メソッド処理を遅延するコレクションを提供する
 
let lazyArr = [1,2,3,4,5].lazy
let middleArr = lazyArr.map { x -> Int in
print(x); return x * 2
}
let endArr = middleArr.map { x in x + 3 }
for _ in endArr { }
Swift code
遅延コレクション(Swift 2.x)
57Ⓒ Classmethod, Inc.
• LazySequenceプロトコルはmap, filter等の変換
メソッド処理を遅延するコレクションを提供する
 
let lazyArr = [1,2,3,4,5].lazy
let middleArr = lazyArr.map { x -> Int in
print(x); return x * 2
}
let endArr = middleArr.map { x in x + 3 }
for _ in endArr { }
Swift code
遅延コレクション生成
遅延コレクション(Swift 2.x)
58Ⓒ Classmethod, Inc.
• LazySequenceプロトコルはmap, filter等の変換
メソッド処理を遅延するコレクションを提供する
 
let lazyArr = [1,2,3,4,5].lazy
let middleArr = lazyArr.map { x -> Int in
print(x); return x * 2
}
let endArr = middleArr.map { x in x + 3 }
for _ in endArr { }
Swift code
遅延コレクション生成
この時点では中の処理は
実施されず、中間のArrayも作成されない
遅延コレクション(Swift 2.x)
59Ⓒ Classmethod, Inc.
• LazySequenceプロトコルはmap, filter等の変換
メソッド処理を遅延するコレクションを提供する
 
let lazyArr = [1,2,3,4,5].lazy
let middleArr = lazyArr.map { x -> Int in
print(x); return x * 2
}
let endArr = middleArr.map { x in x + 3 }
for _ in endArr { }
Swift code
必要になった時にそれまでの変換メソッド処理が実施される。
(1 2 3 4 5が出力される)
遅延コレクション生成
この時点では中の処理は
実施されず、中間のArrayも作成されない
遅延評価のまとめ
60Ⓒ Classmethod, Inc.
Scala Swift
lazy修飾子
遅延引数
遅延コレクション
つけると評価は遅延
つけると評価は遅延
グローバル定数変数は
つけなくても遅延
名前渡しパラメーター @autoclosure
コレクションに対して
.viewで生成
force で正格評価
コレクションに対して
.lazyで生成
必要なときに評価
Topics for today
• ミックスイン
• 正格評価・遅延評価
• 変位指定
61Ⓒ Classmethod, Inc.
変位指定
• リスコフ置換原則
• 共変・反変
• 共変
• 反変
62Ⓒ Classmethod, Inc.
リスコフ置換原則
63Ⓒ Classmethod, Inc.
• リスコフ置換原則
Let Φ(x) be a property provable about
objects x of type T. Then Φ(y) should be true
for objects y of type S where S is a subtype
of T.
Liskov, and Wing(1993)  A Behavioral Notion of Subtyping
リスコフ置換原則
64Ⓒ Classmethod, Inc.
• リスコフ置換原則
  T型のオブジェクトxに関して属性 Φ(x)が真
→ T型の派生型であるS型のオブジェクトyに関して
属性Φ(y)が真であるべき
リスコフ置換原則
65Ⓒ Classmethod, Inc.
• リスコフ置換原則
 SがTの派生型なら
T型の値が使える箇所でS型の値も使える
リスコフ置換原則
66Ⓒ Classmethod, Inc.
• リスコフ置換原則
 SがTの派生型なら
T型の値が使える箇所でS型の値も使える
「派生型」として満たされるべき原則
(必ずしも「継承」を意味しない)
変位指定
• リスコフ置換原則
• 共変・反変
• 共変
• 反変
67Ⓒ Classmethod, Inc.
共変・反変
68Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs
共変・反変
69Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数のない通常の型 
共変・反変
70Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数のない通常の型 
T S
音楽は娯楽の「派生型」として置換可能
共変・反変
71Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数のない通常の型 
→継承関係のみを気にすればうまくいく
T S
音楽は娯楽の「派生型」として置換可能
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
72Ⓒ Classmethod, Inc.
共変・反変
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
73Ⓒ Classmethod, Inc.
共変・反変
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
74Ⓒ Classmethod, Inc.
メタルの作曲家は娯楽の提供者の
「派生型」として置換可能
T S
共変・反変
共変・反変
75Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
共変・反変
76Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
共変・反変
77Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
TS
有機物消費者は竹を食べるパンダの
「派生型」として置換可能
共変・反変
78Ⓒ Classmethod, Inc.
• ある型が別の型の派生型かどうかを判別する
型引数xのある型 
→型引数の継承関係でうまく判断できないケースがある
TS
有機物消費者は竹を食べるパンダの
「派生型」として置換可能
共変・反変
79Ⓒ Classmethod, Inc.
• 共変・反変で
型引数xのある型同士の派生型を判別する
共変(Covariant)型引数の場合
 
共変・反変
80Ⓒ Classmethod, Inc.
• 共変・反変で
型引数xのある型同士の派生型を判別する
共変(Covariant)型引数の場合
→型引数の派生順序を引き継ぐ
 
型引数xの派生順序
「xの提供者」の派生順序
共変・反変
81Ⓒ Classmethod, Inc.
• 共変・反変で
型引数xのある型同士の派生型を判別する
反変(Contravariant)型引数の場合
 
共変・反変
82Ⓒ Classmethod, Inc.
• 共変・反変で
型引数xのある型同士の派生型を判別する
反変(Contravariant)型引数の場合
→型引数の派生順序が反転する
 
型引数xの派生順序
「xの消費者」の派生順序
共変・反変
83Ⓒ Classmethod, Inc.
• 共変・反変で
型引数xのある型同士の派生型を判別する
反変(Contravariant)型引数の場合
→型引数の派生順序が反転する
 
型引数xの派生順序
「xの消費者」の派生順序
PECS
(Producer extends Consumer super)
と呼ばれる基準もある
共変・反変
84Ⓒ Classmethod, Inc.
• 共変・反変で型引数xのある型同士の派生型を判別する
型引数が複数あり、共変・反変が共存する場合
↓ ↑
T
S
U
V
共変・反変
85Ⓒ Classmethod, Inc.
• 共変・反変で型引数xのある型同士の派生型を判別する
型引数が複数あり、共変・反変が共存する場合
↓ ↑
T
S
U
V
TはSの派生型 VはUの派生型
共変・反変
86Ⓒ Classmethod, Inc.
• 共変・反変で型引数xのある型同士の派生型を判別する
型引数が複数あり、共変・反変が共存する場合
反変型引数 共変型引数
↓ ↑
T
S
U
V
TはSの派生型 VはUの派生型
共変・反変
87Ⓒ Classmethod, Inc.
• 共変・反変で型引数xのある型同士の派生型を判別する
型引数が複数あり、共変・反変が共存する場合
反変型引数 共変型引数
↓ ↑↑
T
S
U
V
TはSの派生型 VはUの派生型
[反変S, 共変V]は[反変T, 共変U]の派生型
共変・反変
88Ⓒ Classmethod, Inc.
• 共変・反変で型引数xのある型同士の派生型を判別する
型引数が複数あり、共変・反変が共存する場合
→共変型引数については派生順序を保持、
 反変型引数については派生順序を逆転
反変型引数 共変型引数
↓ ↑↑
T
S
U
V
TはSの派生型 VはUの派生型
[反変S, 共変V]は[反変T, 共変U]の派生型
共変・反変は派生型についての
判定材料を与える
89Ⓒ Classmethod, Inc.
変位指定
• リスコフ置換原則
• 共変・反変
• 共変
• 反変
90Ⓒ Classmethod, Inc.
共変(Scala)
91Ⓒ Classmethod, Inc.
• +を型引数の前につけると共変となる
 sealed abstract class List[+A] …
var anyList: List[Any] = Nil
val intList: List[Int] = List(2, 3, 4)
anyList = intList
Scala code
共変(Scala)
92Ⓒ Classmethod, Inc.
• +を型引数の前につけると共変となる
 sealed abstract class List[+A] …
var anyList: List[Any] = Nil
val intList: List[Int] = List(2, 3, 4)
anyList = intList
Scala code
派生順序は Any > Int
共変(Scala)
93Ⓒ Classmethod, Inc.
• +を型引数の前につけると共変となる
 sealed abstract class List[+A] …
var anyList: List[Any] = Nil
val intList: List[Int] = List(2, 3, 4)
anyList = intList
Scala code
派生順序は Any > Int
型引数の派生順序が保存され、
List[Int] は List[Any]の派生型として扱える
共変(Objective-C)
94Ⓒ Classmethod, Inc.
• __covariantを型引数の前につけると共変となる
 @interface NSArray<__covariant ObjectType>…
NSArray<NSObject *> *anyArray = @[];
NSArray<NSNumber *> *numberArray =
@[@2, @3, @4];
anyArray = numberArray;
Objective-C code
共変(Objective-C)
95Ⓒ Classmethod, Inc.
• __covariantを型引数の前につけると共変となる
 @interface NSArray<__covariant ObjectType>…
NSArray<NSObject *> *anyArray = @[];
NSArray<NSNumber *> *numberArray =
@[@2, @3, @4];
anyArray = numberArray;
Objective-C code
派生順序は NSObject > NSNumber
共変(Objective-C)
96Ⓒ Classmethod, Inc.
• __covariantを型引数の前につけると共変となる
 @interface NSArray<__covariant ObjectType>…
NSArray<NSObject *> *anyArray = @[];
NSArray<NSNumber *> *numberArray =
@[@2, @3, @4];
anyArray = numberArray;
Objective-C code
派生順序は NSObject > NSNumber
型引数の派生順序が保存され、
NSArray<NSNumber *>* は
NSArray<NSObject *>* の派生型として扱える
共変(Swift)
97Ⓒ Classmethod, Inc.
• Array<T>はTについて共変
  struct Array<T> …
var anyArray: [Any] = []
let intArray: [Int] = [2, 3, 4]
anyArray = intArray
Swift code
共変(Swift)
98Ⓒ Classmethod, Inc.
• Array<T>はTについて共変
  struct Array<T> …
var anyArray: [Any] = []
let intArray: [Int] = [2, 3, 4]
anyArray = intArray
Swift code
派生順序は Any > Int
共変(Swift)
99Ⓒ Classmethod, Inc.
• Array<T>はTについて共変
  struct Array<T> …
var anyArray: [Any] = []
let intArray: [Int] = [2, 3, 4]
anyArray = intArray
Swift code
派生順序は Any > Int
型引数の派生順序が保存され、
Array<Int> は Array<Any> の派生型として扱える
共変(Swift)
100Ⓒ Classmethod, Inc.
• Array<T>はTについて共変
  struct Array<T> …
var anyArray: [Any] = []
let intArray: [Int] = [2, 3, 4]
anyArray = intArray
Swift code
派生順序は Any > Int
型引数の派生順序が保存され、
Array<Int> は Array<Any> の派生型として扱える
将来共変を表すためのキーワードが入るかも?(憶測
変位指定
• リスコフ置換原則
• 共変・反変
• 共変
• 反変
101Ⓒ Classmethod, Inc.
反変(Scala)
102Ⓒ Classmethod, Inc.
• -を型引数の前につけると反変となる
 
class Consumer[-T] {
def consume(p: T) = {}
}
var anyConsumer: Consumer[Any] =
new Consumer[Any]()
var intConsumer: Consumer[Int] =
new Consumer[Int]()
intConsumer = anyConsumer
Scala code
反変(Scala)
103Ⓒ Classmethod, Inc.
• -を型引数の前につけると反変となる
 
class Consumer[-T] {
def consume(p: T) = {}
}
var anyConsumer: Consumer[Any] =
new Consumer[Any]()
var intConsumer: Consumer[Int] =
new Consumer[Int]()
intConsumer = anyConsumer
Scala code
派生順序は Any > Int
反変(Scala)
104Ⓒ Classmethod, Inc.
• -を型引数の前につけると反変となる
 
class Consumer[-T] {
def consume(p: T) = {}
}
var anyConsumer: Consumer[Any] =
new Consumer[Any]()
var intConsumer: Consumer[Int] =
new Consumer[Int]()
intConsumer = anyConsumer
Scala code
派生順序は Any > Int
型引数の派生順序が逆転、
Consumer[Any] は Consumer[Int]の派生型として扱える
反変(Objective-C)
105Ⓒ Classmethod, Inc.
• __contravariantを型引数の前につけると反変となる
 @interface Consumer<__contravariant Type>
: NSObject
- (void)consume:(Type)obj;
@end
@implementation Consumer
- (void)consume:(id)obj {}
@end
Objective-C code
反変(Objective-C)
106Ⓒ Classmethod, Inc.
• __contravariantを型引数の前につけると反変となる
 @interface Consumer<__contravariant Type>
: NSObject
- (void)consume:(Type)obj;
@end
@implementation Consumer
- (void)consume:(id)obj {}
@end
Objective-C code
実装の引数にはidを渡す
反変(Objective-C)
107Ⓒ Classmethod, Inc.
• __contravariantを型引数の前につけると反変となる
 
Consumer<NSObject *> *anyConsumer =
[Consumer<NSObject *> new];
Consumer<NSNumber *> *numberConsumer =
[Consumer<NSNumber *> new];
numberConsumer = anyConsumer;
Objective-C code
反変(Objective-C)
108Ⓒ Classmethod, Inc.
• __contravariantを型引数の前につけると反変となる
 
Consumer<NSObject *> *anyConsumer =
[Consumer<NSObject *> new];
Consumer<NSNumber *> *numberConsumer =
[Consumer<NSNumber *> new];
numberConsumer = anyConsumer;
Objective-C code
派生順序は NSObject > NSNumber
反変(Objective-C)
109Ⓒ Classmethod, Inc.
• __contravariantを型引数の前につけると反変となる
 
Consumer<NSObject *> *anyConsumer =
[Consumer<NSObject *> new];
Consumer<NSNumber *> *numberConsumer =
[Consumer<NSNumber *> new];
numberConsumer = anyConsumer;
Objective-C code
派生順序は NSObject > NSNumber
型引数の派生順序が逆転、
Consumer<NSObject *>* は
Consumer<NSNumber *>* の派生型として扱える
反変(Swift 2.1)
110Ⓒ Classmethod, Inc.
• T -> S (関数の型)はTについて反変、Sについて共変
 
func testVariance(foo:(Int) -> Any){ foo(1) }
func innerAnyInt(p1: Any) -> Int{ return 1 }
func innerAnyAny(p1: Any) -> Any{ return 1 }
func innerIntInt(p1: Int) -> Int{ return 1 }
func innerIntAny(p1: Int) -> Any{ return 1 }
Swift code
http://www.uraimo.com/2015/09/29/Swift2.1-Function-Types-Conversion-
Covariance-Contravariance/
反変(Swift 2.1)
111Ⓒ Classmethod, Inc.
• T -> S (関数の型)はTについて反変、Sについて共変
 
func testVariance(foo:(Int) -> Any){ foo(1) }
func innerAnyInt(p1: Any) -> Int{ return 1 }
func innerAnyAny(p1: Any) -> Any{ return 1 }
func innerIntInt(p1: Int) -> Int{ return 1 }
func innerIntAny(p1: Int) -> Any{ return 1 }
Swift code
引数にIntかその上位派生型、
返り値にAnyかその下位派生型をもつ関数を許容
http://www.uraimo.com/2015/09/29/Swift2.1-Function-Types-Conversion-
Covariance-Contravariance/
反変(Swift 2.1)
112Ⓒ Classmethod, Inc.
• T -> S (関数の型)はTについて反変、Sについて共変
 
func testVariance(foo:(Int) -> Any){ foo(1) }
func innerAnyInt(p1: Any) -> Int{ return 1 }
func innerAnyAny(p1: Any) -> Any{ return 1 }
func innerIntInt(p1: Int) -> Int{ return 1 }
func innerIntAny(p1: Int) -> Any{ return 1 }
Swift code
引数にIntかその上位派生型、
返り値にAnyかその下位派生型をもつ関数を許容
http://www.uraimo.com/2015/09/29/Swift2.1-Function-Types-Conversion-
Covariance-Contravariance/
これらの関数は引数がIntかその上位派生型Any
返り値がAnyかその下位派生型Int
反変(Swift 2.1)
113Ⓒ Classmethod, Inc.
• T -> S (関数の型)はTについて反変、Sについて共変
 
testVariance(innerIntAny)
testVariance(innerAnyInt)
testVariance(innerAnyAny)
testVariance(innerIntInt)
Swift code
反変(Swift 2.1)
114Ⓒ Classmethod, Inc.
• T -> S (関数の型)はTについて反変、Sについて共変
 
testVariance(innerIntAny)
testVariance(innerAnyInt)
testVariance(innerAnyAny)
testVariance(innerIntInt)
Swift code
渡される関数の型は全て (Int) -> Any の派生型
反変(Swift 2.1)
115Ⓒ Classmethod, Inc.
• T -> S (関数の型)はTについて反変、Sについて共変
 
testVariance(innerIntAny)
testVariance(innerAnyInt)
testVariance(innerAnyAny)
testVariance(innerIntInt)
Swift code
将来反変を表すためのキーワードが入るかも?(憶測
渡される関数の型は全て (Int) -> Any の派生型
変位指定のまとめ
116Ⓒ Classmethod, Inc.
Scala ObjC Swift
共変
反変
[ +T ]
[ -T ]
<__covariant T>
<__contravariant T>
Array<T>
が対応
T -> S の引数型
Tが対応
• Effective Java 第二版 項目18
http://www.amazon.co.jp/dp/4621066056
• Scala スケーラブルプログラミング §19.3
http://www.amazon.co.jp/dp/4844330845
• Java Generics: What is PECS?
http://stackoverflow.com/questions/2723397/java-generics-
what-is-pecs
117Ⓒ Classmethod, Inc.
References

More Related Content

PDF
続・ゲンバのSwift
PDF
Swift2 の新機能 Protocol Extension
PPTX
Xtend の紹介
PDF
ラムダと invokedynamic の蜜月
PDF
Java 7 invokedynamic の概要
PDF
Java SE 9の紹介: モジュール・システムを中心に
PDF
DVGA writeup
PDF
ATN No.2 Scala事始め
続・ゲンバのSwift
Swift2 の新機能 Protocol Extension
Xtend の紹介
ラムダと invokedynamic の蜜月
Java 7 invokedynamic の概要
Java SE 9の紹介: モジュール・システムを中心に
DVGA writeup
ATN No.2 Scala事始め

What's hot (20)

PDF
第三回ありえる社内勉強会 「いわががのLombok」
PDF
ScalaMatsuri 2016
PPTX
Perlと出会い、Perlを作る
PDF
Aerospike deep dive LDTs
PDF
OpenJDK HotSpot C1Compiler Overview
PDF
TensorFlow Lite Delegateとは?
PDF
gen-class とバイトコード(第3回 gen-class 勉強会資料)
PPTX
Java 9で進化する診断ツール
PDF
JDK 10 へようこそ
PDF
10のJava9で変わるJava8の嫌なとこ!
PDF
Javaセキュアコーディングセミナー東京第1回 講義
PPTX
Retrofit2 &OkHttp 
でAndroidのHTTP通信が快適だにゃん
PDF
第一回社内 Scala 勉強会(一部抜粋)その 2
PDF
今日からできる!簡単 .NET 高速化 Tips
PDF
基礎からのCode Contracts
PDF
PPT
Java9新機能概要
PDF
これからのNashorn
PDF
groovy 2.1.0 20130118
PDF
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
第三回ありえる社内勉強会 「いわががのLombok」
ScalaMatsuri 2016
Perlと出会い、Perlを作る
Aerospike deep dive LDTs
OpenJDK HotSpot C1Compiler Overview
TensorFlow Lite Delegateとは?
gen-class とバイトコード(第3回 gen-class 勉強会資料)
Java 9で進化する診断ツール
JDK 10 へようこそ
10のJava9で変わるJava8の嫌なとこ!
Javaセキュアコーディングセミナー東京第1回 講義
Retrofit2 &OkHttp 
でAndroidのHTTP通信が快適だにゃん
第一回社内 Scala 勉強会(一部抜粋)その 2
今日からできる!簡単 .NET 高速化 Tips
基礎からのCode Contracts
Java9新機能概要
これからのNashorn
groovy 2.1.0 20130118
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
Ad

Viewers also liked (14)

PDF
shinobu.apk #1
PDF
奥行きを意識したプロダクト-iOS9で変わる体験-
PDF
iOS 9 Overview - iOS 9 Bootcamp in Tokyo - 20150930
PDF
Xcode 7 の新しいところ #cm_ios9
PDF
鳥肌必至のニューラルネットワークによる近未来の画像認識技術を体験し、IoTの知られざるパワーを知る
PDF
ユーザーを待たせないためにできること
PDF
iOS9/iPadとマルチタスキング
PDF
Xcode 7で始めるCI
PDF
iOS 9 Bootcamp #6 UIKit
PDF
エンジニアとデザイナーのあいだ
PDF
Composer並列化プラグイン #phpblt
PDF
Advanced nginx in mercari - How to handle over 1,200,000 HTTPS Reqs/Min
PDF
東急ハンズを支える技術
PDF
composerの遅さをまじめに考える #phpstudy
shinobu.apk #1
奥行きを意識したプロダクト-iOS9で変わる体験-
iOS 9 Overview - iOS 9 Bootcamp in Tokyo - 20150930
Xcode 7 の新しいところ #cm_ios9
鳥肌必至のニューラルネットワークによる近未来の画像認識技術を体験し、IoTの知られざるパワーを知る
ユーザーを待たせないためにできること
iOS9/iPadとマルチタスキング
Xcode 7で始めるCI
iOS 9 Bootcamp #6 UIKit
エンジニアとデザイナーのあいだ
Composer並列化プラグイン #phpblt
Advanced nginx in mercari - How to handle over 1,200,000 HTTPS Reqs/Min
東急ハンズを支える技術
composerの遅さをまじめに考える #phpstudy
Ad

Similar to Swift2.x を Scala からみる (20)

PDF
MoteMote Compiler Plugin
PPTX
JavaLearning_1.pptx
PDF
Swift 2.0 大域関数の行方から #swift2symposium
PDF
Synthesijer - HLS frineds 20190511
PDF
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
PPTX
.NET Compiler Platform
PDF
ケーススタディ/実装 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第46回】
PDF
Isomorphic web development with scala and scala.js
PPT
Rpscala2011 0601
PDF
実践 NestJS
PDF
Kink: invokedynamic on a prototype-based language
PDF
Java/Androidセキュアコーディング
PPT
Apexコアデベロッパーセミナー(Apexコード)071010
PDF
形式手法と AWS のおいしい関係。- モデル検査器 Alloy によるインフラ設計技法 #jawsfesta
PDF
Streaming API で実現する クラウド ⇔ イントラ連携
PDF
Grails 2.0.0.M1の話
PDF
Why Reactive Matters #ScalaMatsuri
PDF
めんどくさくない Scala #kwkni_scala
PDF
AndroidーiOS開発比較〜iOSエンジニアから見たAndroidのアレコレ〜
PDF
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
MoteMote Compiler Plugin
JavaLearning_1.pptx
Swift 2.0 大域関数の行方から #swift2symposium
Synthesijer - HLS frineds 20190511
TypeScript ファーストステップ (Rev.2) ~ Any browser. Any host. Any OS. Open Source. ~
.NET Compiler Platform
ケーススタディ/実装 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第46回】
Isomorphic web development with scala and scala.js
Rpscala2011 0601
実践 NestJS
Kink: invokedynamic on a prototype-based language
Java/Androidセキュアコーディング
Apexコアデベロッパーセミナー(Apexコード)071010
形式手法と AWS のおいしい関係。- モデル検査器 Alloy によるインフラ設計技法 #jawsfesta
Streaming API で実現する クラウド ⇔ イントラ連携
Grails 2.0.0.M1の話
Why Reactive Matters #ScalaMatsuri
めんどくさくない Scala #kwkni_scala
AndroidーiOS開発比較〜iOSエンジニアから見たAndroidのアレコレ〜
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~

More from Yuichi Adachi (10)

PDF
Seminar on Quantum Computation & Quantum Information part28
PDF
Seminar on Quantum Computation & Quantum Information part19
PDF
Seminar on Quantum Computation & Quantum Information part15
PDF
ゲンバのSwift
PDF
Seminar on Quantum Computation & Quantum Information part14
PDF
VIPER アーキテクチャによる iOS アプリの設計
PDF
[iOS8] 新たな線形代数ライブラリ Linear Algebra
PDF
Swiftの新機能 Optional
PDF
ユニットテスト初学者がKiwiFramework非同期テストで失敗した
KEY
Applicative functor
Seminar on Quantum Computation & Quantum Information part28
Seminar on Quantum Computation & Quantum Information part19
Seminar on Quantum Computation & Quantum Information part15
ゲンバのSwift
Seminar on Quantum Computation & Quantum Information part14
VIPER アーキテクチャによる iOS アプリの設計
[iOS8] 新たな線形代数ライブラリ Linear Algebra
Swiftの新機能 Optional
ユニットテスト初学者がKiwiFramework非同期テストで失敗した
Applicative functor

Swift2.x を Scala からみる

  • 2. 2 安達 勇一 • 2013/12 入社 • TwitterID: @UsrNameu1 • Github: https://github.com/ UsrNameu1 • Blog: http://dev.classmethod.jp/ author/yad • ここ半年はサーバーサイドメイン
  • 3. Topics for today • ミックスイン • 正格評価・遅延評価 • 変位指定 3Ⓒ Classmethod, Inc.
  • 4. Topics for today • ミックスイン • 正格評価・遅延評価 • 変位指定 4Ⓒ Classmethod, Inc.
  • 5. ミックスイン • ミックスイン • 抽象インターフェイス • デフォルト実装 • ミックスイン対象制限 5Ⓒ Classmethod, Inc.
  • 6. ミックスイン 6Ⓒ Classmethod, Inc. • ミックスイン(mix-in)とは? クラスが「本来の型」に加えて、なんらかの任意の振 る舞いを提供していることを宣言するために、クラスが 実装する型 Bloch(2008)  Effective Java 2nd edition
  • 7. ミックスイン • ミックスイン • 抽象インターフェイス • デフォルト実装 • ミックスイン対象制限 7Ⓒ Classmethod, Inc.
  • 8. 抽象インターフェイス(Scala) 8Ⓒ Classmethod, Inc. • traitは抽象インターフェイスをサポートしている trait AbstractTrait { type DataType val constant: DataType var variable: DataType def method(): DataType } Scala code
  • 9. 抽象インターフェイス(Scala) 9Ⓒ Classmethod, Inc. • traitは抽象インターフェイスをサポートしている trait AbstractTrait { type DataType val constant: DataType var variable: DataType def method(): DataType } 抽象型メンバー、定数、変数、メソッドが定義できる Scala code
  • 10. 抽象インターフェイス(Swift) 10Ⓒ Classmethod, Inc. • protocolは抽象インターフェイスをサポートしている protocol AbstractProtocol { typealias DataType var constant: DataType { get } var variable: DataType { get set } func method() -> DataType init(t: DataType) subscript(i: Int) -> DataType { get } func + (lhs: DataType, rhs: DataType) -> DataType } Swift code
  • 11. 抽象インターフェイス(Swift) 11Ⓒ Classmethod, Inc. • protocolは抽象インターフェイスをサポートしている protocol AbstractProtocol { typealias DataType var constant: DataType { get } var variable: DataType { get set } func method() -> DataType init(t: DataType) subscript(i: Int) -> DataType { get } func + (lhs: DataType, rhs: DataType) -> DataType } 抽象型メンバー、プロパティ、メソッド、イニシャライザ サブスクリプト、演算子が定義できる Swift code
  • 12. ミックスイン • ミックスイン • 抽象インターフェイス • デフォルト実装 • ミックスイン対象制限 12Ⓒ Classmethod, Inc.
  • 13. デフォルト実装(Scala) 13Ⓒ Classmethod, Inc. • traitはデフォルト実装をサポートしている trait AbstractTrait { type DataType = String val constant: DataType = “aa” var variable: DataType = “aaa” def method(): DataType = { “aaaa” } } Scala code
  • 14. デフォルト実装(Scala) 14Ⓒ Classmethod, Inc. • traitはデフォルト実装をサポートしている trait AbstractTrait { type DataType = String val constant: DataType = “aa” var variable: DataType = “aaa” def method(): DataType = { “aaaa” } } デフォルトの実装をtraitの各メンバーに対して定義できる Scala code
  • 15. デフォルト実装(Swift 2.x) 15Ⓒ Classmethod, Inc. • protocol extensionはデフォルト実装をサポートしている extension AbstractProtocol { typealias DataType = String var constant: DataType { return “a” } func method() -> DataType { return “aa” } } Swift code
  • 16. デフォルト実装(Swift 2.x) 16Ⓒ Classmethod, Inc. • protocol extensionはデフォルト実装をサポートしている extension AbstractProtocol { typealias DataType = String var constant: DataType { return “a” } func method() -> DataType { return “aa” } } デフォルトの実装をprotocolの各メンバーに対して定義できる Swift code
  • 17. ミックスイン • ミックスイン • 抽象インターフェイス • デフォルト実装 • ミックスイン対象制限 17Ⓒ Classmethod, Inc.
  • 18. ミックスイン対象制限(Scala) 18Ⓒ Classmethod, Inc. • traitは自分型アノテーションで継承の対象になる型を 限定できる trait AbstractTrait { self: SomeClass => def method(): String = { “aaaa” } } Scala code
  • 19. ミックスイン対象制限(Scala) 19Ⓒ Classmethod, Inc. • traitは自分型アノテーションで継承の対象になる型を 限定できる trait AbstractTrait { self: SomeClass => def method(): String = { “aaaa” } } Scala code ミックスインの対象になる型をSomeClassに限定できる →AbstractTraitはSomeClassと  そのサブ型からしか継承できない
  • 20. ミックスイン対象制限(Swift 2.x) 20Ⓒ Classmethod, Inc. • protocol extensionのSelfへの制約によって デフォルト実装が使える継承の対象となる型を制限できる extension AbstractProtocol where Self: SomeClass { func method() -> String { return “aa” } } Swift code
  • 21. ミックスイン対象制限(Swift 2.x) 21Ⓒ Classmethod, Inc. • protocol extensionのSelfへの制約によって デフォルト実装が使える継承の対象となる型を制限できる extension AbstractProtocol where Self: SomeClass { func method() -> String { return “aa” } } デフォルトの実装を使える型はSomeClassとそのサブ型のみ Swift code
  • 22. ミックスイン対象制限(Swift 2.x) 22Ⓒ Classmethod, Inc. • protocol extensionのSelfへの制約によって デフォルト実装が使える継承の対象となる型を制限できる extension AbstractProtocol where Self: SomeClass { func method() -> String { return “aa” } } デフォルトの実装を使える型はSomeClassとそのサブ型のみ Swift code See also→ http://www.slideshare.net/UsrNameu1/swift2-protocol-extension
  • 23. ミックスインのまとめ 23Ⓒ Classmethod, Inc. Scala Swift 抽象インターフェイス デフォルト実装 ミックスイン対象型への制約 trait protocol trait protocol extension traitでの 自分型アノテーション protocol extensionでの Self への制約
  • 24. Topics for today • ミックスイン • 正格評価・遅延評価 • 変位指定 24Ⓒ Classmethod, Inc.
  • 25. 正格評価・ 遅延評価 • 正格評価・遅延評価 • lazy修飾子 • 遅延引数 • 遅延コレクション 25Ⓒ Classmethod, Inc.
  • 26. 正格評価・遅延評価 26Ⓒ Classmethod, Inc. • 評価(evaluation) とは? 式から値を計算し、取り出す操作
  • 27. 正格評価・遅延評価 27Ⓒ Classmethod, Inc. • 評価(evaluation) とは? 式から値を計算し、取り出す操作 let a = 1 + 1 Swift code
  • 28. 正格評価・遅延評価 28Ⓒ Classmethod, Inc. • 評価(evaluation) とは? 式から値を計算し、取り出す操作 let a = 1 + 1 1 + 1という式から2を計算し、取り出す Swift code
  • 29. 正格評価・遅延評価 29Ⓒ Classmethod, Inc. • 評価(evaluation) とは? 式から値を計算し、取り出す操作 let a = 1 + 1 1 + 1という式から2を計算し、取り出す a という名前の定数に代入する Swift code
  • 30. 正格評価・遅延評価 30Ⓒ Classmethod, Inc. • 正格評価(strict evaluation) とは?  評価結果が使用されるタイミングに関係なく  即時に行われる評価のこと func add(a: Int, _ b: Int) -> Int { return a + b } struct Component { let c = add(1, 1) } Swift code
  • 31. 正格評価・遅延評価 31Ⓒ Classmethod, Inc. • 正格評価(strict evaluation) とは?  評価結果が使用されるタイミングに関係なく  即時に行われる評価のこと func add(a: Int, _ b: Int) -> Int { return a + b } struct Component { let c = add(1, 1) } cが用いられるタイミングに関係なく インスタンス生成時に評価される Swift code
  • 32. 正格評価・遅延評価 32Ⓒ Classmethod, Inc. • 遅延評価(strict evaluation) とは?  即時に行われず、後々必要になったタイミングで  行われる評価のこと func add(a: Int, _ b: Int) -> Int { return a + b } struct LazyComponent { lazy var d = add(1, 2) } Swift code
  • 33. 正格評価・遅延評価 33Ⓒ Classmethod, Inc. • 遅延評価(strict evaluation) とは?  即時に行われず、後々必要になったタイミングで  行われる評価のこと func add(a: Int, _ b: Int) -> Int { return a + b } struct LazyComponent { lazy var d = add(1, 2) } dが用いられるタイミングで評価される Swift code
  • 34. 正格評価・ 遅延評価 • 正格評価・遅延評価 • lazy修飾子 • 遅延引数 • 遅延コレクション 34Ⓒ Classmethod, Inc.
  • 35. lazy修飾子(Scala) 35Ⓒ Classmethod, Inc. • lazyをval(定数)の前につけると遅延評価になる   object LazyConstants { lazy val const: String = { println("computed") "constant" } } val a = LazyConstants.const Scala code
  • 36. lazy修飾子(Scala) 36Ⓒ Classmethod, Inc. • lazyをval(定数)の前につけると遅延評価になる   object LazyConstants { lazy val const: String = { println("computed") "constant" } } val a = LazyConstants.const Scala code 宣言時には評価されない
  • 37. lazy修飾子(Scala) 37Ⓒ Classmethod, Inc. • lazyをval(定数)の前につけると遅延評価になる   object LazyConstants { lazy val const: String = { println("computed") "constant" } } val a = LazyConstants.const Scala code 宣言時には評価されない アクセス時に評価され、 computed が出力される
  • 38. lazy修飾子(Swift) 38Ⓒ Classmethod, Inc. • lazyをvar(変数)の前につけると遅延評価になる   class LazyConstants { lazy var const: String = { print("computed") return "constant" }() } let constants = LazyConstants() let const = constants.const Swift code
  • 39. lazy修飾子(Swift) 39Ⓒ Classmethod, Inc. • lazyをvar(変数)の前につけると遅延評価になる   class LazyConstants { lazy var const: String = { print("computed") return "constant" }() } let constants = LazyConstants() let const = constants.const Swift code インスタンス生成時には評価されない
  • 40. lazy修飾子(Swift) 40Ⓒ Classmethod, Inc. • lazyをvar(変数)の前につけると遅延評価になる   class LazyConstants { lazy var const: String = { print("computed") return "constant" }() } let constants = LazyConstants() let const = constants.const Swift code インスタンス生成時には評価されない プロパティアクセス時に評価され、 computed が出力される
  • 41. lazy修飾子(Swift) 41Ⓒ Classmethod, Inc. • グローバル変数、定数はlazy修飾子をつけなくても 自動的に遅延評価になる   let someConst: String = { print("computed") return "constant" }() let length = someConst.utf8.count Swift code
  • 42. lazy修飾子(Swift) 42Ⓒ Classmethod, Inc. • グローバル変数、定数はlazy修飾子をつけなくても 自動的に遅延評価になる   let someConst: String = { print("computed") return "constant" }() let length = someConst.utf8.count Swift code この時点では評価されない
  • 43. lazy修飾子(Swift) 43Ⓒ Classmethod, Inc. • グローバル変数、定数はlazy修飾子をつけなくても 自動的に遅延評価になる   let someConst: String = { print("computed") return "constant" }() let length = someConst.utf8.count Swift code この時点では評価されない アクセス時に評価され、 computed が出力される
  • 44. 正格評価・ 遅延評価 • 正格評価・遅延評価 • lazy修飾子 • 遅延引数 • 遅延コレクション 44Ⓒ Classmethod, Inc.
  • 45. 遅延引数(Scala) 45Ⓒ Classmethod, Inc. • 名前渡しパラメーターは引数の評価を遅延する   val assertionsEnabled = true def byNameAssert(pred: => Boolean) = if (assertionsEnabled && !pred) throw new AssertionError byNameAssert(2 > 5) Scala code
  • 46. 遅延引数(Scala) 46Ⓒ Classmethod, Inc. • 名前渡しパラメーターは引数の評価を遅延する   val assertionsEnabled = true def byNameAssert(pred: => Boolean) = if (assertionsEnabled && !pred) throw new AssertionError byNameAssert(2 > 5) Scala code assertionsEnabled が真の時 初めて引数 pred を評価する
  • 47. 遅延引数(Scala) 47Ⓒ Classmethod, Inc. • 名前渡しパラメーターは引数の評価を遅延する   val assertionsEnabled = true def byNameAssert(pred: => Boolean) = if (assertionsEnabled && !pred) throw new AssertionError byNameAssert(2 > 5) Scala code assertionsEnabled が真の時 初めて引数 pred を評価する 評価は引数を渡すタイミングではなく、 byNameAssert内部の処理が走るタイミングで行われる
  • 48. 遅延引数(Swift) 48Ⓒ Classmethod, Inc. • @autoclosureは引数の評価を遅延する   func myAnd( lhs: Bool, @autoclosure _ rhs: () -> Bool ) -> Bool { if lhs { return rhs() } else { return false } } let result = myAnd(true, 1 < 2) Swift code
  • 49. 遅延引数(Swift) 49Ⓒ Classmethod, Inc. • @autoclosureは引数の評価を遅延する   func myAnd( lhs: Bool, @autoclosure _ rhs: () -> Bool ) -> Bool { if lhs { return rhs() } else { return false } } let result = myAnd(true, 1 < 2) Swift code lhs が真の時初めて引数 rhs を評価する
  • 50. 遅延引数(Swift) 50Ⓒ Classmethod, Inc. • @autoclosureは引数の評価を遅延する   func myAnd( lhs: Bool, @autoclosure _ rhs: () -> Bool ) -> Bool { if lhs { return rhs() } else { return false } } let result = myAnd(true, 1 < 2) Swift code lhs が真の時初めて引数 rhs を評価する 評価は引数を渡すタイミングではなく、 myAnd内部の処理が走るタイミングで行われる
  • 51. 正格評価・ 遅延評価 • 正格評価・遅延評価 • lazy修飾子 • 遅延引数 • 遅延コレクション 51Ⓒ Classmethod, Inc.
  • 52. 遅延コレクション(Scala) 52Ⓒ Classmethod, Inc. • ビューはmap, filter等の変換メソッド処理を 遅延するコレクションを提供する   val vectorView = Vector(1 to 5: _*).view val middleView = vectorView.map { x => println(x); x * 2 } middleView.map { _ + 3 }.force Scala code
  • 53. 遅延コレクション(Scala) 53Ⓒ Classmethod, Inc. • ビューはmap, filter等の変換メソッド処理を 遅延するコレクションを提供する   val vectorView = Vector(1 to 5: _*).view val middleView = vectorView.map { x => println(x); x * 2 } middleView.map { _ + 3 }.force Scala code 遅延コレクション生成
  • 54. 遅延コレクション(Scala) 54Ⓒ Classmethod, Inc. • ビューはmap, filter等の変換メソッド処理を 遅延するコレクションを提供する   val vectorView = Vector(1 to 5: _*).view val middleView = vectorView.map { x => println(x); x * 2 } middleView.map { _ + 3 }.force Scala code 遅延コレクション生成 この時点では中の処理は実施されず 中間のVectorも作成されない
  • 55. 遅延コレクション(Scala) 55Ⓒ Classmethod, Inc. • ビューはmap, filter等の変換メソッド処理を 遅延するコレクションを提供する   val vectorView = Vector(1 to 5: _*).view val middleView = vectorView.map { x => println(x); x * 2 } middleView.map { _ + 3 }.force Scala codeforceメソッドで正格コレクションに戻され、 それまでの変換メソッド処理が実施される。      (1 2 3 4 5が出力される) 遅延コレクション生成 この時点では中の処理は実施されず 中間のVectorも作成されない
  • 56. 遅延コレクション(Swift 2.x) 56Ⓒ Classmethod, Inc. • LazySequenceプロトコルはmap, filter等の変換 メソッド処理を遅延するコレクションを提供する   let lazyArr = [1,2,3,4,5].lazy let middleArr = lazyArr.map { x -> Int in print(x); return x * 2 } let endArr = middleArr.map { x in x + 3 } for _ in endArr { } Swift code
  • 57. 遅延コレクション(Swift 2.x) 57Ⓒ Classmethod, Inc. • LazySequenceプロトコルはmap, filter等の変換 メソッド処理を遅延するコレクションを提供する   let lazyArr = [1,2,3,4,5].lazy let middleArr = lazyArr.map { x -> Int in print(x); return x * 2 } let endArr = middleArr.map { x in x + 3 } for _ in endArr { } Swift code 遅延コレクション生成
  • 58. 遅延コレクション(Swift 2.x) 58Ⓒ Classmethod, Inc. • LazySequenceプロトコルはmap, filter等の変換 メソッド処理を遅延するコレクションを提供する   let lazyArr = [1,2,3,4,5].lazy let middleArr = lazyArr.map { x -> Int in print(x); return x * 2 } let endArr = middleArr.map { x in x + 3 } for _ in endArr { } Swift code 遅延コレクション生成 この時点では中の処理は 実施されず、中間のArrayも作成されない
  • 59. 遅延コレクション(Swift 2.x) 59Ⓒ Classmethod, Inc. • LazySequenceプロトコルはmap, filter等の変換 メソッド処理を遅延するコレクションを提供する   let lazyArr = [1,2,3,4,5].lazy let middleArr = lazyArr.map { x -> Int in print(x); return x * 2 } let endArr = middleArr.map { x in x + 3 } for _ in endArr { } Swift code 必要になった時にそれまでの変換メソッド処理が実施される。 (1 2 3 4 5が出力される) 遅延コレクション生成 この時点では中の処理は 実施されず、中間のArrayも作成されない
  • 60. 遅延評価のまとめ 60Ⓒ Classmethod, Inc. Scala Swift lazy修飾子 遅延引数 遅延コレクション つけると評価は遅延 つけると評価は遅延 グローバル定数変数は つけなくても遅延 名前渡しパラメーター @autoclosure コレクションに対して .viewで生成 force で正格評価 コレクションに対して .lazyで生成 必要なときに評価
  • 61. Topics for today • ミックスイン • 正格評価・遅延評価 • 変位指定 61Ⓒ Classmethod, Inc.
  • 62. 変位指定 • リスコフ置換原則 • 共変・反変 • 共変 • 反変 62Ⓒ Classmethod, Inc.
  • 63. リスコフ置換原則 63Ⓒ Classmethod, Inc. • リスコフ置換原則 Let Φ(x) be a property provable about objects x of type T. Then Φ(y) should be true for objects y of type S where S is a subtype of T. Liskov, and Wing(1993)  A Behavioral Notion of Subtyping
  • 64. リスコフ置換原則 64Ⓒ Classmethod, Inc. • リスコフ置換原則   T型のオブジェクトxに関して属性 Φ(x)が真 → T型の派生型であるS型のオブジェクトyに関して 属性Φ(y)が真であるべき
  • 65. リスコフ置換原則 65Ⓒ Classmethod, Inc. • リスコフ置換原則  SがTの派生型なら T型の値が使える箇所でS型の値も使える
  • 66. リスコフ置換原則 66Ⓒ Classmethod, Inc. • リスコフ置換原則  SがTの派生型なら T型の値が使える箇所でS型の値も使える 「派生型」として満たされるべき原則 (必ずしも「継承」を意味しない)
  • 67. 変位指定 • リスコフ置換原則 • 共変・反変 • 共変 • 反変 67Ⓒ Classmethod, Inc.
  • 68. 共変・反変 68Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs
  • 69. 共変・反変 69Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数のない通常の型 
  • 70. 共変・反変 70Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数のない通常の型  T S 音楽は娯楽の「派生型」として置換可能
  • 71. 共変・反変 71Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数のない通常の型  →継承関係のみを気にすればうまくいく T S 音楽は娯楽の「派生型」として置換可能
  • 74. • ある型が別の型の派生型かどうかを判別する 型引数xのある型  74Ⓒ Classmethod, Inc. メタルの作曲家は娯楽の提供者の 「派生型」として置換可能 T S 共変・反変
  • 75. 共変・反変 75Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数xのある型 
  • 76. 共変・反変 76Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数xのある型 
  • 77. 共変・反変 77Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数xのある型  TS 有機物消費者は竹を食べるパンダの 「派生型」として置換可能
  • 78. 共変・反変 78Ⓒ Classmethod, Inc. • ある型が別の型の派生型かどうかを判別する 型引数xのある型  →型引数の継承関係でうまく判断できないケースがある TS 有機物消費者は竹を食べるパンダの 「派生型」として置換可能
  • 79. 共変・反変 79Ⓒ Classmethod, Inc. • 共変・反変で 型引数xのある型同士の派生型を判別する 共変(Covariant)型引数の場合  
  • 80. 共変・反変 80Ⓒ Classmethod, Inc. • 共変・反変で 型引数xのある型同士の派生型を判別する 共変(Covariant)型引数の場合 →型引数の派生順序を引き継ぐ   型引数xの派生順序 「xの提供者」の派生順序
  • 81. 共変・反変 81Ⓒ Classmethod, Inc. • 共変・反変で 型引数xのある型同士の派生型を判別する 反変(Contravariant)型引数の場合  
  • 82. 共変・反変 82Ⓒ Classmethod, Inc. • 共変・反変で 型引数xのある型同士の派生型を判別する 反変(Contravariant)型引数の場合 →型引数の派生順序が反転する   型引数xの派生順序 「xの消費者」の派生順序
  • 83. 共変・反変 83Ⓒ Classmethod, Inc. • 共変・反変で 型引数xのある型同士の派生型を判別する 反変(Contravariant)型引数の場合 →型引数の派生順序が反転する   型引数xの派生順序 「xの消費者」の派生順序 PECS (Producer extends Consumer super) と呼ばれる基準もある
  • 84. 共変・反変 84Ⓒ Classmethod, Inc. • 共変・反変で型引数xのある型同士の派生型を判別する 型引数が複数あり、共変・反変が共存する場合 ↓ ↑ T S U V
  • 85. 共変・反変 85Ⓒ Classmethod, Inc. • 共変・反変で型引数xのある型同士の派生型を判別する 型引数が複数あり、共変・反変が共存する場合 ↓ ↑ T S U V TはSの派生型 VはUの派生型
  • 86. 共変・反変 86Ⓒ Classmethod, Inc. • 共変・反変で型引数xのある型同士の派生型を判別する 型引数が複数あり、共変・反変が共存する場合 反変型引数 共変型引数 ↓ ↑ T S U V TはSの派生型 VはUの派生型
  • 87. 共変・反変 87Ⓒ Classmethod, Inc. • 共変・反変で型引数xのある型同士の派生型を判別する 型引数が複数あり、共変・反変が共存する場合 反変型引数 共変型引数 ↓ ↑↑ T S U V TはSの派生型 VはUの派生型 [反変S, 共変V]は[反変T, 共変U]の派生型
  • 88. 共変・反変 88Ⓒ Classmethod, Inc. • 共変・反変で型引数xのある型同士の派生型を判別する 型引数が複数あり、共変・反変が共存する場合 →共変型引数については派生順序を保持、  反変型引数については派生順序を逆転 反変型引数 共変型引数 ↓ ↑↑ T S U V TはSの派生型 VはUの派生型 [反変S, 共変V]は[反変T, 共変U]の派生型
  • 90. 変位指定 • リスコフ置換原則 • 共変・反変 • 共変 • 反変 90Ⓒ Classmethod, Inc.
  • 91. 共変(Scala) 91Ⓒ Classmethod, Inc. • +を型引数の前につけると共変となる  sealed abstract class List[+A] … var anyList: List[Any] = Nil val intList: List[Int] = List(2, 3, 4) anyList = intList Scala code
  • 92. 共変(Scala) 92Ⓒ Classmethod, Inc. • +を型引数の前につけると共変となる  sealed abstract class List[+A] … var anyList: List[Any] = Nil val intList: List[Int] = List(2, 3, 4) anyList = intList Scala code 派生順序は Any > Int
  • 93. 共変(Scala) 93Ⓒ Classmethod, Inc. • +を型引数の前につけると共変となる  sealed abstract class List[+A] … var anyList: List[Any] = Nil val intList: List[Int] = List(2, 3, 4) anyList = intList Scala code 派生順序は Any > Int 型引数の派生順序が保存され、 List[Int] は List[Any]の派生型として扱える
  • 94. 共変(Objective-C) 94Ⓒ Classmethod, Inc. • __covariantを型引数の前につけると共変となる  @interface NSArray<__covariant ObjectType>… NSArray<NSObject *> *anyArray = @[]; NSArray<NSNumber *> *numberArray = @[@2, @3, @4]; anyArray = numberArray; Objective-C code
  • 95. 共変(Objective-C) 95Ⓒ Classmethod, Inc. • __covariantを型引数の前につけると共変となる  @interface NSArray<__covariant ObjectType>… NSArray<NSObject *> *anyArray = @[]; NSArray<NSNumber *> *numberArray = @[@2, @3, @4]; anyArray = numberArray; Objective-C code 派生順序は NSObject > NSNumber
  • 96. 共変(Objective-C) 96Ⓒ Classmethod, Inc. • __covariantを型引数の前につけると共変となる  @interface NSArray<__covariant ObjectType>… NSArray<NSObject *> *anyArray = @[]; NSArray<NSNumber *> *numberArray = @[@2, @3, @4]; anyArray = numberArray; Objective-C code 派生順序は NSObject > NSNumber 型引数の派生順序が保存され、 NSArray<NSNumber *>* は NSArray<NSObject *>* の派生型として扱える
  • 97. 共変(Swift) 97Ⓒ Classmethod, Inc. • Array<T>はTについて共変   struct Array<T> … var anyArray: [Any] = [] let intArray: [Int] = [2, 3, 4] anyArray = intArray Swift code
  • 98. 共変(Swift) 98Ⓒ Classmethod, Inc. • Array<T>はTについて共変   struct Array<T> … var anyArray: [Any] = [] let intArray: [Int] = [2, 3, 4] anyArray = intArray Swift code 派生順序は Any > Int
  • 99. 共変(Swift) 99Ⓒ Classmethod, Inc. • Array<T>はTについて共変   struct Array<T> … var anyArray: [Any] = [] let intArray: [Int] = [2, 3, 4] anyArray = intArray Swift code 派生順序は Any > Int 型引数の派生順序が保存され、 Array<Int> は Array<Any> の派生型として扱える
  • 100. 共変(Swift) 100Ⓒ Classmethod, Inc. • Array<T>はTについて共変   struct Array<T> … var anyArray: [Any] = [] let intArray: [Int] = [2, 3, 4] anyArray = intArray Swift code 派生順序は Any > Int 型引数の派生順序が保存され、 Array<Int> は Array<Any> の派生型として扱える 将来共変を表すためのキーワードが入るかも?(憶測
  • 101. 変位指定 • リスコフ置換原則 • 共変・反変 • 共変 • 反変 101Ⓒ Classmethod, Inc.
  • 102. 反変(Scala) 102Ⓒ Classmethod, Inc. • -を型引数の前につけると反変となる   class Consumer[-T] { def consume(p: T) = {} } var anyConsumer: Consumer[Any] = new Consumer[Any]() var intConsumer: Consumer[Int] = new Consumer[Int]() intConsumer = anyConsumer Scala code
  • 103. 反変(Scala) 103Ⓒ Classmethod, Inc. • -を型引数の前につけると反変となる   class Consumer[-T] { def consume(p: T) = {} } var anyConsumer: Consumer[Any] = new Consumer[Any]() var intConsumer: Consumer[Int] = new Consumer[Int]() intConsumer = anyConsumer Scala code 派生順序は Any > Int
  • 104. 反変(Scala) 104Ⓒ Classmethod, Inc. • -を型引数の前につけると反変となる   class Consumer[-T] { def consume(p: T) = {} } var anyConsumer: Consumer[Any] = new Consumer[Any]() var intConsumer: Consumer[Int] = new Consumer[Int]() intConsumer = anyConsumer Scala code 派生順序は Any > Int 型引数の派生順序が逆転、 Consumer[Any] は Consumer[Int]の派生型として扱える
  • 105. 反変(Objective-C) 105Ⓒ Classmethod, Inc. • __contravariantを型引数の前につけると反変となる  @interface Consumer<__contravariant Type> : NSObject - (void)consume:(Type)obj; @end @implementation Consumer - (void)consume:(id)obj {} @end Objective-C code
  • 106. 反変(Objective-C) 106Ⓒ Classmethod, Inc. • __contravariantを型引数の前につけると反変となる  @interface Consumer<__contravariant Type> : NSObject - (void)consume:(Type)obj; @end @implementation Consumer - (void)consume:(id)obj {} @end Objective-C code 実装の引数にはidを渡す
  • 107. 反変(Objective-C) 107Ⓒ Classmethod, Inc. • __contravariantを型引数の前につけると反変となる   Consumer<NSObject *> *anyConsumer = [Consumer<NSObject *> new]; Consumer<NSNumber *> *numberConsumer = [Consumer<NSNumber *> new]; numberConsumer = anyConsumer; Objective-C code
  • 108. 反変(Objective-C) 108Ⓒ Classmethod, Inc. • __contravariantを型引数の前につけると反変となる   Consumer<NSObject *> *anyConsumer = [Consumer<NSObject *> new]; Consumer<NSNumber *> *numberConsumer = [Consumer<NSNumber *> new]; numberConsumer = anyConsumer; Objective-C code 派生順序は NSObject > NSNumber
  • 109. 反変(Objective-C) 109Ⓒ Classmethod, Inc. • __contravariantを型引数の前につけると反変となる   Consumer<NSObject *> *anyConsumer = [Consumer<NSObject *> new]; Consumer<NSNumber *> *numberConsumer = [Consumer<NSNumber *> new]; numberConsumer = anyConsumer; Objective-C code 派生順序は NSObject > NSNumber 型引数の派生順序が逆転、 Consumer<NSObject *>* は Consumer<NSNumber *>* の派生型として扱える
  • 110. 反変(Swift 2.1) 110Ⓒ Classmethod, Inc. • T -> S (関数の型)はTについて反変、Sについて共変   func testVariance(foo:(Int) -> Any){ foo(1) } func innerAnyInt(p1: Any) -> Int{ return 1 } func innerAnyAny(p1: Any) -> Any{ return 1 } func innerIntInt(p1: Int) -> Int{ return 1 } func innerIntAny(p1: Int) -> Any{ return 1 } Swift code http://www.uraimo.com/2015/09/29/Swift2.1-Function-Types-Conversion- Covariance-Contravariance/
  • 111. 反変(Swift 2.1) 111Ⓒ Classmethod, Inc. • T -> S (関数の型)はTについて反変、Sについて共変   func testVariance(foo:(Int) -> Any){ foo(1) } func innerAnyInt(p1: Any) -> Int{ return 1 } func innerAnyAny(p1: Any) -> Any{ return 1 } func innerIntInt(p1: Int) -> Int{ return 1 } func innerIntAny(p1: Int) -> Any{ return 1 } Swift code 引数にIntかその上位派生型、 返り値にAnyかその下位派生型をもつ関数を許容 http://www.uraimo.com/2015/09/29/Swift2.1-Function-Types-Conversion- Covariance-Contravariance/
  • 112. 反変(Swift 2.1) 112Ⓒ Classmethod, Inc. • T -> S (関数の型)はTについて反変、Sについて共変   func testVariance(foo:(Int) -> Any){ foo(1) } func innerAnyInt(p1: Any) -> Int{ return 1 } func innerAnyAny(p1: Any) -> Any{ return 1 } func innerIntInt(p1: Int) -> Int{ return 1 } func innerIntAny(p1: Int) -> Any{ return 1 } Swift code 引数にIntかその上位派生型、 返り値にAnyかその下位派生型をもつ関数を許容 http://www.uraimo.com/2015/09/29/Swift2.1-Function-Types-Conversion- Covariance-Contravariance/ これらの関数は引数がIntかその上位派生型Any 返り値がAnyかその下位派生型Int
  • 113. 反変(Swift 2.1) 113Ⓒ Classmethod, Inc. • T -> S (関数の型)はTについて反変、Sについて共変   testVariance(innerIntAny) testVariance(innerAnyInt) testVariance(innerAnyAny) testVariance(innerIntInt) Swift code
  • 114. 反変(Swift 2.1) 114Ⓒ Classmethod, Inc. • T -> S (関数の型)はTについて反変、Sについて共変   testVariance(innerIntAny) testVariance(innerAnyInt) testVariance(innerAnyAny) testVariance(innerIntInt) Swift code 渡される関数の型は全て (Int) -> Any の派生型
  • 115. 反変(Swift 2.1) 115Ⓒ Classmethod, Inc. • T -> S (関数の型)はTについて反変、Sについて共変   testVariance(innerIntAny) testVariance(innerAnyInt) testVariance(innerAnyAny) testVariance(innerIntInt) Swift code 将来反変を表すためのキーワードが入るかも?(憶測 渡される関数の型は全て (Int) -> Any の派生型
  • 116. 変位指定のまとめ 116Ⓒ Classmethod, Inc. Scala ObjC Swift 共変 反変 [ +T ] [ -T ] <__covariant T> <__contravariant T> Array<T> が対応 T -> S の引数型 Tが対応
  • 117. • Effective Java 第二版 項目18 http://www.amazon.co.jp/dp/4621066056 • Scala スケーラブルプログラミング §19.3 http://www.amazon.co.jp/dp/4844330845 • Java Generics: What is PECS? http://stackoverflow.com/questions/2723397/java-generics- what-is-pecs 117Ⓒ Classmethod, Inc. References