Skip to content

Instantly share code, notes, and snippets.

@KentarouKanno
Last active April 9, 2016 01:35
Show Gist options
  • Save KentarouKanno/dc6c15d4a20c88581732 to your computer and use it in GitHub Desktop.
Save KentarouKanno/dc6c15d4a20c88581732 to your computer and use it in GitHub Desktop.
Optional

Optional

★ Optional型

//=> Optional(1)

var optionalOne: Int? = 1
var optionalOne = 1 as Int?
var optionalOne: Int? = .Some(1)
var optionalOne: Optional<Int> = 1
var optionalOne = Optional.Some(1)
var optionalOne: Optional<Int> = Int(1)
var optionalOne: Int? = Optional<Int>(1)
var optionalOne: Optional<Int> = Optional<Int>(1)

//=> nil
var optionalNil: Optional<Int> = nil
var optionalNil: Int?
var optionalNil: Int? = nil
var optionalNil = nil as Int?
var optionalNil: Optional<Int> = .None
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
    case None
    case Some(Wrapped)
    /// Construct a `nil` instance.
    public init()
    /// Construct a non-`nil` instance that stores `some`.
    public init(_ some: Wrapped)
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    @warn_unused_result
    public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
    /// Returns `nil` if `self` is nil, `f(self!)` otherwise.
    @warn_unused_result
    public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
    /// Create an instance initialized with `nil`.
    public init(nilLiteral: ())
}

★ 非Optional型

//=> 1

var one = 1
var one: Int = 1
var one = Int(1)

// Optional型のUnwrapは「!」が必要
var one = optionalOne!

// implicitlyUnwrappedOptional型のUnwrapは「!」があっても無くてもOK
var one = implicitlyUnwrappedOptionalOne
var one = implicitlyUnwrappedOptionalOne!

★ Implicitly Unwrapped Optional型

//=> 1

var implicitlyUnwrappedOptionalOne: Int! = 1
var implicitlyUnwrappedOptionalOne = 1 as Int!
var implicitlyUnwrappedOptionalOne: ImplicitlyUnwrappedOptional<Int> = 1
var implicitlyUnwrappedOptionalOne = ImplicitlyUnwrappedOptional.Some(1)
var implicitlyUnwrappedOptionalOne: ImplicitlyUnwrappedOptional<Int> = .Some(1)

//=> nil
var implicitlyUnwrappedOptionalNil: Int!
var implicitlyUnwrappedOptionalNil: Int! = nil
var implicitlyUnwrappedOptionalNil = nil as Int!
var implicitlyUnwrappedOptionalNil: ImplicitlyUnwrappedOptional<Int>
var implicitlyUnwrappedOptionalNil: ImplicitlyUnwrappedOptional<Int> = .None
var implicitlyUnwrappedOptionalNil: ImplicitlyUnwrappedOptional<Int> = nil
public enum ImplicitlyUnwrappedOptional<Wrapped> : _Reflectable, NilLiteralConvertible {
    case None
    case Some(Wrapped)
    /// Construct a `nil` instance.
    public init()
    /// Construct a non-`nil` instance that stores `some`.
    public init(_ some: Wrapped)
    /// Construct an instance from an explicitly unwrapped optional
    /// (`Wrapped?`).
    public init(_ v: Wrapped?)
    /// Create an instance initialized with `nil`.
    public init(nilLiteral: ())
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    @warn_unused_result
    public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U!
    /// Returns `nil` if `self` is nil, `f(self!)` otherwise.
    @warn_unused_result
    public func flatMap<U>(@noescape f: (Wrapped) throws -> U!) rethrows -> U!
}

★ Forced unwrapping

// Optional型
var optionalInt: Int? = 1

var result = optionalInt! + 2
//=> 3

// Optional型がnilの場合はエラーになります

★ Optional chaining

let name: String? = "name"
let result = name?.uppercaseString
//=> "Optional("NAME")"


let name: String? = nil
let result = name?.uppercaseString
//=> nil

// -------------------

class Sample {
    func hoge() {
        print("hoge")
    }
}

// Optional chainingで処理が成功した場合、戻り値が無いと空のタプルが返される
// nilで無ければ処理は成功と思って良い

let obj: Sample? = Sample()
var returnObj = obj?.hoge()
//=> "Optional(())"

let obj: Sample? = nil
var returnObj = obj?.hoge()
//=> nil

★ Optional binding

// Optional型
var optionalInt: Int? = 1

// if - let
if let optionalInt = optionalInt {
    print(optionalInt + 2)
    //=> 3
}

if let intValue: Int = optionalInt {
    print(intValue + 2)
    //=> 3
}

if - case 

if case .Some(let optionalInt) = optionalInt {
    print(optionalInt + 2)
    //=> 3
}

// Optional Pattern
if case let optionalInt? = optionalInt {
    print(optionalInt + 2)
    //=> 3
}

// 上記は下記のシンタックスシュガー
switch (optionalInt) {
case .Some(let optionalInt):
    print(optionalInt + 2)
default:
    break
}


// guard
let num = "5"
  
guard let number = Int(num) else {
    print("nil")
    return
}
 
let resutl = number + 2
//=> 7

// -------------------

let resut: Int

if let value1 = Int("5"), value2 = Int("7") where value1 < value2 {
    // value1, value2ともにUnwrapできて value1 < value2の条件がtrueの場合
    resut = value1 + value2
    //=> 12
}

// ----------------

var optionalIntArray: [Int?]? = []
optionalIntArray?.append(5)

if let intVal = optionalIntArray, var value = intVal[0] {
    value += 5
    //=> 10
}

★ 比較演算子

// Optional型 (nilでもエラーにはならない)
var optionalInt: Int? = 1

print(optionalInt == 1)
//=> true

if optionalInt == 1 {
    // 判定はできるが使用する値はUnwrapしなければ使用できない
    optionalInt! + 2
}

print(optionalInt >= 1)
//=> true

print(optionalInt >  1)
//=> false

print(optionalInt <= 1)
//=> true

print(optionalInt <  1)
//=> false

print(optionalInt != 1)
//=> false

★ nil結合演算子

// "D"に対応するキーが無い(nil)ので ?? の後の値("d")が代入される
// nilの場合の既定値が設定できる

let dict = ["A": "a", "B": "b", "C": "c"]
let result = dict["D"] ?? "d"
//=> "d"

//  Optional Chainingの様な書き方もできる
let x: Int? = nil, y: Int? = nil, z: Int? = 5
var val = x ?? y ?? z
//=> Optional(5)

★ nilの判定

let value: Int? = Int("2")
var result: Int = 0

if value != nil {
    // nil判定ではUnwrapされないので使用するときは『!』でUnwrapしている
    result = value! + 3
    //=> 5
}

★ 失敗のあるイニシャライザ

class Sample {
    var value: Int
    init?(val: Int) {
        self.value = val
        
        if val > 10 {
            return nil
        }
    }
}


let sample1 = Sample(val: 5)
//=> Optional<Sample>.Type

let sample2 = Sample(val: 20)
//=> nil 

★ map

// mapの中ではnil同士の計算ができる戻されるのはnil or Optional(数値)

var num: Int? = nil
var result: Int?
result = num.map{ $0 + $0 }
//=> nil

var num: Int? = 5
var result: Int?
result = num.map{ $0 + $0 }
//=> Optional(10)

★ flatMap

// Int?の配列からnilを除いたInt型の配列を作成する

var optionalIntArray = [Int?]([1, 2, 3, nil, 5])
var intArray: [Int] = optionalIntArray.flatMap { $0 }
//=> [1, 2, 3, 5]


let a: String = "2"
let b: String = "3"
let c = Int(a).flatMap { a0 in Int(b).flatMap { b0 in a0 + b0 }}
//=> Optional(5)
// OptionalのBool型
let boolValue: Bool? = nil

// OptionalのSting型
let stringValue: String? = nil

// OptionalのInt型
let intValue: Int? = nil

// OptionalのDouble型
let doubleValue: Double? = nil

// OptionalのDictionary型
let dictionaryValue: Dictionary<String,String>? = nil
let dictionaryValue: [String: String]? = nil

// OptionalのArray型
let arrayValue: Array<Int>? = nil
let arrayValue: [Int]? = nil

let arrayValue: [Int?] = [nil]
let arrayValue: [Int?]? = [nil]
let arrayValue: [Int?]? = nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment