Edited at

吾輩はCompound Typeである 〜 タプル型と関数型の正体を探る

More than 3 years have passed since last update.

image


image


Extensionの好循環 のコピー.png


image



関数型やタプル型にExtensionを書く方法は?



Not Found

The requested way not found in this language.


image



型(Type)



型(Type)


  • named type

  • compound type



Type > named type



named type

= 固有の名前を与えて定義できる型


  • class type

  • struct type

  • enum type

  • protocol type



だいたいの型は、named type

public struct Array<Element> :

CollectionType, MutableCollectionType, _DestructorSafeContainer

public struct Dictionary<Key : Hashable, Value> :

CollectionType, DictionaryLiteralConvertible

public enum Optional<Wrapped> :

_Reflectable, NilLiteralConvertible



名前がある=extendできる



Type > compound type



compound type

= 名前のない型


  • tuple type

  • function type



名前がない=extensionも書けない



Type > compound type > tuple type



tuple type

括弧で囲まれた、

0個以上の型のカンマ区切りリスト

(Melon, String, Bool)



tuple type

 

コロンで要素名をつけられる

(melon: Melon, farmName: String, isTasty: Bool)


let tuple = (

melon: Melon(),
farmName: "夕張",
isTasty: true
)

スクリーンショット 2016-07-10 13.41.47.png


ちなみに、型Tをひとつだけもつタプルは型Tと同じ扱いになります

// 1個の要素をもつタプルに、タプルでない型を代入可能

let p: ((Int)) = 1
// ※ 型は let p: ((Int)) タプル型だと認識されている

// タプルでない型に、1個の要素をもつタプルを代入可能
let r: String = (((("a"))))
// ※ 型は let r: String

// タプルの存在を意識せず比較も可能
let f: ((((((Int))))) -> (((((((((String))))))))))
= { return $0 == p ? r : r }
// ※ 関数の型は書いたとおりに
// let f: ((((((Int))))) -> (((((((((String)))))))))) になっている



Type > compound type > function type



突然ですがここでクイズです

() -> Void

Q. この関数型の、引数・戻り値は?

 



突然ですがここでクイズです

() -> Void

Q. この関数型の、引数・戻り値は?

A. 何も引数に取らず、何も返さない関数?



🙅


() -> Void

Q. この関数型の、引数・戻り値は?


正解:

空タプルを引数に取り、空タプルを返す関数



function type

image



function type

image

() -> Void



function type

image

() -> Void

image



function type

image

() -> Void

つまり、


  • parameter type: ()

  • return type: ()


検証してみよう

func hoge() {}

let p = ()
let r = hoge(p)
print(r)


検証してみよう

func hoge() {}

let p = ()
let r = hoge(p) // ←空タプルを引数として渡せる
print(r) // () ←空タプルを戻り値として受けられる


そう考えると…

(Int) -> Melon

([Melon]) -> Melon?

(melon: Melon, farmName: String, isTasty: Bool) -> Melon?

関数の引数って、タプルに見えてきませんか?



というか、実際タプルなんです。


func taste(melon: Melon, farmName: String, isTasty: Bool) {

print(farmName + "の🍈は" + (isTasty ? "おいしい" : "まずい"))
}

let tuple = (melon: Melon(), farmName: "夕張", isTasty: true)

//実際Swift2ではこれで通ったりする
taste(tuple)


Swift3では関数の引数にタプルを渡すのはエラーになるけど、一段抽象化すると、通る。

func taste(melon: Melon, farmName: String, isTasty: Bool) {

print(farmName + "の🍈は" + (isTasty ? "おいしい" : "まずい"))
}

let tuple = (melon: Melon(), farmName: "夕張", isTasty: true)

//taste(tuple)
// Error: passing 3 arguments to a callee as a single tuple value has been removed in Swift 3
// see also: https://github.com/apple/swift/blob/master/test/Misc/misc_diagnostics.swift#L136

func apply<P, R>(to function: (P) -> R, parameter: P) -> R {
return function(parameter)
}

apply(to: taste, parameter: tuple)


function typeを

parameter type -> return type という

シンプルなcompound typeとして表現するために、

tuple というcompound typeが役に立っているようだ



まとめ

compound typeを理解すると、型の世界がもっとよく理解できる!



で、結局、何故compound typeに対してはExtensionが書けないのかって?

…。



で、結局、何故compound typeに対してはExtensionが書けないのかって?

…。

…何故でしょうね?

何か分かる方いらっしゃったらお話しましょう!



参考

The Swift Programming Language (Swift 2.2): Types

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html