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

  • 15
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

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